library(RSQLite)
library(dbplyr)
package ‘dbplyr’ was built under R version 3.6.2Registered S3 methods overwritten by 'dbplyr':
  method         from
  print.tbl_lazy     
  print.tbl_sql      
library(janitor)
package ‘janitor’ was built under R version 3.6.2
Attaching package: ‘janitor’

The following objects are masked from ‘package:stats’:

    chisq.test, fisher.test
library(lubridate)
package ‘lubridate’ was built under R version 3.6.2
Attaching package: ‘lubridate’

The following objects are masked from ‘package:base’:

    date, intersect, setdiff, union
library(datasets)
library(ggthemes)
library(gganimate)
package ‘gganimate’ was built under R version 3.6.2Loading required package: ggplot2
package ‘ggplot2’ was built under R version 3.6.2
library(modelr)
package ‘modelr’ was built under R version 3.6.2
library(broom)
package ‘broom’ was built under R version 3.6.2
Attaching package: ‘broom’

The following object is masked from ‘package:modelr’:

    bootstrap
library(ggfortify)
package ‘ggfortify’ was built under R version 3.6.2
library(infer)
package ‘infer’ was built under R version 3.6.2
library(MASS)
package ‘MASS’ was built under R version 3.6.2
library(tseries)
Registered S3 method overwritten by 'quantmod':
  method            from
  as.zoo.data.frame zoo 

    ‘tseries’ version: 0.10-47

    ‘tseries’ is a package for time series analysis and computational
    finance.

    See ‘library(help="tseries")’ for details.
library(forecast)
package ‘forecast’ was built under R version 3.6.2Registered S3 methods overwritten by 'forecast':
  method                 from     
  autoplot.Arima         ggfortify
  autoplot.acf           ggfortify
  autoplot.ar            ggfortify
  autoplot.bats          ggfortify
  autoplot.decomposed.ts ggfortify
  autoplot.ets           ggfortify
  autoplot.forecast      ggfortify
  autoplot.stl           ggfortify
  autoplot.ts            ggfortify
  fitted.ar              ggfortify
  fortify.ts             ggfortify
  residuals.ar           ggfortify
library(fable)
package ‘fable’ was built under R version 3.6.2Loading required package: fabletools
package ‘fabletools’ was built under R version 3.6.2
Attaching package: ‘fabletools’

The following objects are masked from ‘package:forecast’:

    accuracy, forecast

The following object is masked from ‘package:infer’:

    generate
library(fabletools)
library(tsibble)
package ‘tsibble’ was built under R version 3.6.2
Attaching package: ‘tsibble’

The following object is masked from ‘package:lubridate’:

    interval
library(tsibbledata)
package ‘tsibbledata’ was built under R version 3.6.2
library(feasts)
package ‘feasts’ was built under R version 3.6.2
library(tidyverse)
── Attaching packages ─────────────────────────────────────── tidyverse 1.3.0 ──
✓ tibble  3.0.3     ✓ dplyr   1.0.2
✓ tidyr   1.1.2     ✓ stringr 1.4.0
✓ readr   1.3.1     ✓ forcats 0.5.0
✓ purrr   0.3.4     
package ‘tibble’ was built under R version 3.6.2package ‘tidyr’ was built under R version 3.6.2package ‘purrr’ was built under R version 3.6.2package ‘dplyr’ was built under R version 3.6.2── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
x lubridate::as.difftime() masks base::as.difftime()
x broom::bootstrap()       masks modelr::bootstrap()
x lubridate::date()        masks base::date()
x dplyr::filter()          masks stats::filter()
x dplyr::ident()           masks dbplyr::ident()
x lubridate::intersect()   masks base::intersect()
x tsibble::interval()      masks lubridate::interval()
x dplyr::lag()             masks stats::lag()
x dplyr::select()          masks MASS::select()
x lubridate::setdiff()     masks base::setdiff()
x dplyr::sql()             masks dbplyr::sql()
x lubridate::union()       masks base::union()
library(leaflet)
Registered S3 methods overwritten by 'htmltools':
  method               from         
  print.html           tools:rstudio
  print.shiny.tag      tools:rstudio
  print.shiny.tag.list tools:rstudio
Registered S3 method overwritten by 'htmlwidgets':
  method           from         
  print.htmlwidget tools:rstudio

2. Creating some initial visualisations

Fires per year

year_plot <- fires_small %>%
  group_by(fire_year) %>%
  summarise(num_fires =n())
`summarise()` ungrouping output (override with `.groups` argument)
year_plot %>%
  ggplot +
  aes(x = fire_year, y = num_fires) +
  geom_point() +
  geom_line() +
  ylim(0, 120000) +
  ggtitle("Amount of fires per year 1992-2015\n") + 
  xlab("\nYear") +
  ylab("Number of Fires\n") +
  theme_bw() +
  theme(plot.title = element_text(hjust = 0.5))

There is a lot of variation in the data between years. Visually it looks like a repeating pattern is occurring every 5 years or so with 4 peaks visible within this reporting period. Having looked at the historic weather for that date range these peaks seems to coincide with recorded heatwaves in 2000, 2006 and 2011.(1)

https://en.wikipedia.org/wiki/List_of_heat_waves

I will try to create a linear model to hopefully show any increase or decrease of fires over time (see seperate workbook). As this is time series data a linear model will not fit, but it could be interesting to see if it identifies a general underlying trend.

Fires per month

fires_small %>%
  mutate(year_month = make_date(fire_year, discovery_moy)) %>%
  group_by(year_month) %>%
  summarise(num_fires = n()) %>%
  ggplot +
  aes(x = year_month, y = num_fires) +
  geom_line(col = "dark blue") +
  ggtitle("Amount of fires per month 1992-2015\n") + 
  xlab("\nYear") +
  ylab("Number of Fires\n") +
  theme_bw() +
  theme(plot.title = element_text(hjust = 0.5))
`summarise()` ungrouping output (override with `.groups` argument)

Peaks are still shown to be occurring in the summers. The 2006 heatwave is especially visible.

Using the SARIMA model.

monthly <- fires_small %>%
  mutate(year_month = make_date(fire_year, discovery_moy)) %>%
  group_by(year_month) %>%
  summarise(num_fires = n())
`summarise()` ungrouping output (override with `.groups` argument)
write_csv(monthly, path = "clean_data/monthly.csv")

monthly

Continued on seperate worksheet

Fires per day

fires_small %>%
  group_by(discovery_date) %>%
  summarise(num_fires = n()) %>%
  ggplot +
  aes(x = discovery_date, y = num_fires) +
  geom_line(col = "dark blue") +
  ggtitle("Amount of fires per day 1992-2015\n") + 
  xlab("\nYear") +
  ylab("Number of Fires\n") +
  theme_bw() +
  theme(plot.title = element_text(hjust = 0.5))
`summarise()` ungrouping output (override with `.groups` argument)

This shows a typical time series plot with a cyclic variation due to warmer weather in the summer time.

Fires by day of year

fires_small %>%
  group_by(discovery_doy) %>%
  summarise(num_fires = n()) %>%
  ggplot(aes(x = discovery_doy, y = num_fires)) +
  geom_line(col = "dark blue") +
  ggtitle("Amount of fires per day of year, for combined years 1992-2015\n") + 
  xlab("\nDay of Year") +
  ylab("Number of Fires\n") +
  theme_bw() +
  theme(plot.title = element_text(hjust = 0.5))
`summarise()` ungrouping output (override with `.groups` argument)

The are peaks around day 60-110 and a big peak around 180.

Checking the data to see exactly where the peak occurs

fires_small %>%
  group_by(discovery_doy) %>%
  summarise(num_fires = n()) %>%
  arrange(desc(num_fires))
`summarise()` ungrouping output (override with `.groups` argument)

The 2 highest days of the year are on 185 and 186, which happens to be Independence Day (4th July) on a normal year and a leap year retrospectively. So I imagine most of the extra fires (literally over double the normal amount) are caused by fireworks.

Fires by month of year

fires_small %>%
  group_by(discovery_moy) %>%
  summarise(num_fires = n()) %>%
  ggplot(aes(x = discovery_moy, y = num_fires)) +
  geom_col(fill = "dark blue", col = "black") +
  ggtitle("Amount of fires per month of year, for combined years 1992-2015\n") + 
  xlab("\nMonth of Year") +
  ylab("Number of Fires\n") +
  theme_bw() +
  theme(plot.title = element_text(hjust = 0.5))
`summarise()` ungrouping output (override with `.groups` argument)

There are 2 definite peaks during the year. March and April are possibly due to the US “Spring Break”, where schools and Universities are stopped and so families are likely to be on vacation during that period possibly visiting National Parks. July and August is also Summer Break for school with both families visiting Parks and hot weather likely causes of fire outbreaks. I will have a look at the data and see if there is anything related to vacation time that could corroborate this.

https://en.wikipedia.org/wiki/School_holidays_in_the_United_States

mar_apr_causes <- fires_small %>%
  dplyr::filter(discovery_moy == "Mar" | discovery_moy == "April") %>%
  group_by(stat_cause_descr) %>%
  summarise(num_fires_mar_apr = n()) %>%
  arrange(desc(num_fires_mar_apr))
`summarise()` ungrouping output (override with `.groups` argument)
  
may_june_causes <- fires_small %>%
  dplyr::filter(discovery_moy == "May" | discovery_moy == "June") %>%
  group_by(stat_cause_descr) %>%
  summarise(num_fires_may_june = n()) %>%
  arrange(desc(num_fires_may_june))
`summarise()` ungrouping output (override with `.groups` argument)
mar_apr_causes$num_fires_may_june <- may_june_causes$num_fires_may_june

mar_apr_causes

Although there is a large increase in fires due to debris burning, arson and miscellaneous in March and April, in May and June the number of fires by children, campfire and smoking is all higher so there is no definite proof that school breaks are to cause for the spikes in March and April each year over the whole data period.

Fires by cause

options(scipen = 999)

fires_small %>%
  group_by(stat_cause_descr) %>%
  summarise(num_fires = n()) %>%
  ggplot +
  aes(reorder(x = stat_cause_descr, num_fires), y = num_fires) +
  geom_col(fill = "dark blue") + 
  coord_flip() +
  ggtitle("Amount of fires by cause, for combined years 1992-2015\n") + 
  xlab("Cause of fire\n") +
  ylab("\nNumber of Fires") +
  theme_bw() +
  theme(plot.title = element_text(hjust = 0.5))
`summarise()` ungrouping output (override with `.groups` argument)

NA

Fire avg size by cause

fires_small %>%
  group_by(stat_cause_descr) %>%
  summarise(avg_size = mean(fire_size)) %>%
  ggplot +
  aes(reorder(x = stat_cause_descr, avg_size), y = avg_size) +
  geom_col(fill = "dark blue") + 
  coord_flip() +
  ggtitle("Average size of fire per cause, for combined years 1992-2015\n") + 
  xlab("Cause of fire\n") +
  ylab("\nSize of fire (Square Miles)") +
  theme_bw() +
  theme(plot.title = element_text(hjust = 0.5))
`summarise()` ungrouping output (override with `.groups` argument)

Avg burn time by cause

fires_small %>%
  summarise(num_na = sum(is.na(cont_date)))

Literally half the data is missing for burn time, making it very difficult to do any meaningful analysis so I shall not consider burn time at this time.

Fires by size

fires_small %>%
  group_by(fire_size_class) %>%
  summarise(num_fires = n()) %>%
  ggplot +
  aes(x = fire_size_class, y = num_fires, fill = fire_size_class) +
  geom_col(col = "black") +
  scale_fill_manual(values = c("#016450", "#02818a", "#3690c0", "#67a9cf",
                               "#a6bddb", "#d0d1e6","#f6eff7"),
                    name = "Fire Size Classification",
                    breaks = c("A", "B", "C", "D", "E", "F", "G"),
                    labels = c("A: < 1/4 acre", "B: 1/4 to 10 acres", 
                               "C: 10 to 100 acres", "D: 100 to 300 acres", 
                               "E: 300 to 1000 acres", "F: 1000 to 5000 acres", 
                               "G: More than 5000 acres")) +
  ggtitle("Amount of fires types in the years 1992-2015\n") + 
  xlab("\nFire Size Classification") +
  ylab("Number of Fires\n") +
  theme_bw() +
  theme(plot.title = element_text(hjust = 0.5)) 
`summarise()` ungrouping output (override with `.groups` argument)

NA
NA

Geo Spatial wrangling

To make it easier to visually detect frequency of wildfires between states I want display it in a map format. As I’m using ggplot2 already I’m going to also use it for maps with the geom_polygon(), coord_map() along with the ggthemes theme_map() functions.

I’m not entirely sure what geo-spatial information is being held with in the sqlite database file, I’ve made a few attempts to retrieve it but have been unsuccessful. Therefore I’m going to utelise the datasets package which includes various bits of information on the US States, including coordinates for state boundaries.

# State boundary co-ordinates from 'datasets' package

state_map <- map_data("state")
state_map

Annoyingly it doesn’t have the abbreviation of the State, only the full name so I need to add that in. Luckily the ‘datasets’ package also has a vector of States names and abbreviations so I shall make a tibble with them both in.

state.abb
 [1] "AL" "AK" "AZ" "AR" "CA" "CO" "CT" "DE" "FL" "GA" "HI" "ID" "IL" "IN" "IA"
[16] "KS" "KY" "LA" "ME" "MD" "MA" "MI" "MN" "MS" "MO" "MT" "NE" "NV" "NH" "NJ"
[31] "NM" "NY" "NC" "ND" "OH" "OK" "OR" "PA" "RI" "SC" "SD" "TN" "TX" "UT" "VT"
[46] "VA" "WA" "WV" "WI" "WY" "DC" "PR"
state.name
 [1] "Alabama"              "Alaska"               "Arizona"             
 [4] "Arkansas"             "California"           "Colorado"            
 [7] "Connecticut"          "Delaware"             "Florida"             
[10] "Georgia"              "Hawaii"               "Idaho"               
[13] "Illinois"             "Indiana"              "Iowa"                
[16] "Kansas"               "Kentucky"             "Louisiana"           
[19] "Maine"                "Maryland"             "Massachusetts"       
[22] "Michigan"             "Minnesota"            "Mississippi"         
[25] "Missouri"             "Montana"              "Nebraska"            
[28] "Nevada"               "New Hampshire"        "New Jersey"          
[31] "New Mexico"           "New York"             "North Carolina"      
[34] "North Dakota"         "Ohio"                 "Oklahoma"            
[37] "Oregon"               "Pennsylvania"         "Rhode Island"        
[40] "South Carolina"       "South Dakota"         "Tennessee"           
[43] "Texas"                "Utah"                 "Vermont"             
[46] "Virginia"             "Washington"           "West Virginia"       
[49] "Wisconsin"            "Wyoming"              "District of Columbia"
[52] "Puerto Rico"         
state.abb
 [1] "AL" "AK" "AZ" "AR" "CA" "CO" "CT" "DE" "FL" "GA" "HI" "ID" "IL" "IN" "IA"
[16] "KS" "KY" "LA" "ME" "MD" "MA" "MI" "MN" "MS" "MO" "MT" "NE" "NV" "NH" "NJ"
[31] "NM" "NY" "NC" "ND" "OH" "OK" "OR" "PA" "RI" "SC" "SD" "TN" "TX" "UT" "VT"
[46] "VA" "WA" "WV" "WI" "WY"

The state_map dataframe is in lower case and has the column name ‘region’. I shall change the state_list tibble to be the same format so they can be joined together.

state_list <- tibble(state = state.abb, region = tolower(state.name))

Joing state_list to fires_small datasets

fires_states <- fires_small %>%
  left_join(state_list, by = "state")

fires_states

Checking the join has worked and there are no missing values.

fires_states %>%
  filter(is.na(region))

There does seem to be 22,147 NAs in the ‘region’ column we just made. Scrolling through there are 2 missing States of ‘PR’ and ‘DC’ in the states_list tibble.

After some quick research it seems that there are only 50 States in the US. Washington DC is techincally not counted as a state but as a Federal District, as it is the seat of government, so that was why it wasn’t included in the States tibble originally. PR is Puerto Rico and is also not a state but the largest US territory.

I shall add DC and PR into the state_list and re-join it.

# Adding 2 new states

state.abb <- append(state.abb, c("DC", "PR"))
state.name <- append(state.name, c("District of Columbia", "Puerto Rico"))

state_list <- tibble(state = state.abb, region = tolower(state.name))
# Re-joing tibbles

fires_states <- fires_small %>%
  left_join(state_list, by = "state")
# Checking the join has worked properly and there are no NAs

fires_states %>%
  filter(is.na(region))
Warning in `[<-.data.frame`(`*tmp*`, is_list, value = list(`23` = "<S3: blob>")) :
  replacement element 1 has 1 row to replace 0 rows
# Code below brings up a "vector memory exhausted (limit reached?)" error

# fires_joined <- fires_states %>%
#  right_join(state_map, by = "region")

The data set and geo information is too big to join so I’m going to do a summarise first to get the number of fires per region first.

fires_joined <- fires_states %>% 
    select(region) %>%
    group_by(region) %>%
    summarise(num_fires = n()) %>%
    right_join(state_map, by = "region")
`summarise()` ungrouping output (override with `.groups` argument)

Result!! Now doing first geo spatial visualisation

Total Wildfires per state from 1992-2015

fires_joined %>% 
    ggplot +
    (aes(x = long, y = lat, group = group, fill = num_fires)) + 
    geom_polygon() + 
    geom_path(color = "white") + 
    scale_fill_distiller(name = "Number of Fires", palette = "PuBuGn") + 
    theme_map() + 
    coord_map("mollweide") +  
    ggtitle("Total US Wildfires from 1992-2015") + 
    theme(plot.title = element_text(hjust = 0.5))

3. Geo Spatial Visualisations

The dataset has a cause of fire column so I shall now create some causation plots.

Getting list of fire causes

fires_states %>%
  distinct(stat_cause_descr) %>%
  arrange(-desc(stat_cause_descr))

Total fire by cause in tabular form

fires_states %>%
  select(stat_cause_descr) %>%
  group_by(stat_cause_descr) %>%
  summarise(num_fires = n ()) %>%
  arrange(desc(num_fires))
`summarise()` ungrouping output (override with `.groups` argument)
NA

Number of fires by state in tabular form

fires_states %>%
  select(region) %>%
  group_by(region) %>%
  summarise(num_fires = n()) %>%
  arrange(desc(num_fires))
`summarise()` ungrouping output (override with `.groups` argument)

As the cause needs to be filtered before the map join, I’m going to either going to have to repeat a whole load of the same code in every single plot or write a function that will do it for me with, saving a lot of typing!

# Function for plotting cause of fire

cause <- function(cause) {
  fires_states %>%
    filter(stat_cause_descr == cause) %>%
    dplyr::select(region) %>%
    group_by(region) %>%
    summarise(num_fires = n ()) %>%
    right_join(state_map, by = "region") %>%
    ggplot +
    (aes(x = long, y = lat, group = group, fill = num_fires)) + 
    geom_polygon() + 
    geom_path(color = "white") + 
    scale_fill_distiller(name = "Number of fires", palette = "PuBuGn") + 
    theme_map() + 
    coord_map("mollweide") + 
    ggtitle(paste0("Total US Wildfires caused by ", cause, " from 1992-2015")) + 
    theme(plot.title = element_text(hjust = 0.5))
}

Wildfires caused by Arson

cause("Arson")
`summarise()` ungrouping output (override with `.groups` argument)

Arson does seem more prevalent in the SE states of Mississippi, Georgia, Alabama and also the western state of California.

Wildfires caused by Campfire

cause("Campfire")
`summarise()` ungrouping output (override with `.groups` argument)

Campfires are the most prevalent in the Western states of Oregon, California and Arizona.

Wildfires caused by Children

cause("Children")
`summarise()` ungrouping output (override with `.groups` argument)

Fires by children are spread about the country, but the most prevalent states are California in the West, Alabama and South Carolina and New Jersey in the east.

Wildfires caused by Debris Burning

cause("Debris Burning")
`summarise()` ungrouping output (override with `.groups` argument)

Fires by burning debris are mostly in the southern warmer states of Texas, Georgia and North Carolina.

Wildfires caused by Equiment Use

cause("Equipment Use")
`summarise()` ungrouping output (override with `.groups` argument)

Most of the fires caused by equipment seem to be in California

Wildfires caused by Fireworks

cause("Fireworks")
`summarise()` ungrouping output (override with `.groups` argument)

Most of the fires caused by fireworks seem to be in the north of the country. Primarily South Dakota, Montana and Washington state.

Wildfires caused by Lightning

cause("Lightning")
`summarise()` ungrouping output (override with `.groups` argument)

Apart from a hotspot of lightning strikes in Florida, the vast majority of fires caused by lightning are in the West of the country. With the 3 most affected states being California, Oregon and Arizona.

Wildfires caused by Miscellious

cause("Miscellaneous")
`summarise()` ungrouping output (override with `.groups` argument)

There seems to be quite a few miscellaneous classifications in California, Texas and New York.

Wildfires caused by Missing/Undefined

cause("Missing/Undefined")
`summarise()` ungrouping output (override with `.groups` argument)

The states with the most missing or undefined data is North and South Carolina, Oklahoma and California.

Wildfires caused by Powerline

cause("Powerline")
`summarise()` ungrouping output (override with `.groups` argument)

Texas has the largest amount of wildfires caused by powerlines. This is possibly due to the warm climate and the large proportion of the state that is dry grasslands used for agriculture. (1)

  1. https://uk.reuters.com/article/us-wildfires-texas/trees-and-power-lines-caused-major-texas-fire-idUSTRE78J76A20110920

Wildfires caused by Railroad

cause("Railroad")
`summarise()` ungrouping output (override with `.groups` argument)

By far Florida has the most wildfires caused by railroads. I find this rather strange and will do some further investigation.

Wildfires caused by Smoking

cause("Smoking")
`summarise()` ungrouping output (override with `.groups` argument)

Fires caused by smoking seem to be spread around the country, but mainly on the east and west coasts.

Wildfires caused by Structure

cause("Structure")
`summarise()` ungrouping output (override with `.groups` argument)

South Dakota has the largest proportion of fires caused by structures.

Unsurprisingly the southern states seem to have more occurences of wildifre in general, no doubt due to the warmer climate at their latitudes leading to dryer ground cover which cab act as fuel. Also the 1st and 3rd states with the highest number of fires are also the 2 largest States by size. However the 2nd highest State is Georgia, which although it is in the South of the country is only an average sized State. Therefore to get a better picture of what is going on I’m going to look at the proportion of fires occuring by square mile by normalising the State size.

The dataset package also has the area in square miles of each state included in the state.area vector.

state.area
 [1]  51609 589757 113909  53104 158693 104247   5009   2057  58560  58876
[11]   6450  83557  56400  36291  56290  82264  40395  48523  33215  10577
[21]   8257  58216  84068  47716  69686 147138  77227 110540   9304   7836
[31] 121666  49576  52586  70665  41222  69919  96981  45333   1214  31055
[41]  77047  42244 267339  84916   9609  40815  68192  24181  56154  97914
length(state.area)
[1] 50

Annoyingly it also only has 50 states not 52 so I will need to add in DC and PR back in.

(Area figures obtained from Wikipedia)

DC = 68 miles^2 PR = 3515 miles^2

# To make my life easier I'm going to remove the state.abb and .name files and make the tibble again, adding in the land area figures at the same time to make sure they are in the correct order.

rm(state.abb)
rm(state.name)

state.abb <- append(state.abb, c("DC", "PR"))
state.name <- append(state.name, c("District of Columbia", "Puerto Rico"))
state.area <- append(state.area, c("68", "3515"))

state_list <- tibble(state = state.abb, region = tolower(state.name), area = as.numeric(state.area))
# Re-joining tibbles

fires_states <- fires_small %>%
  left_join(state_list, by = "state")

Normalising States area sizes

fires_states %>%
  select(region, area) %>%
  group_by(region) %>%
  summarise(num_fires = n()) %>%
  arrange(desc(num_fires))
fires_states %>%
  select(region, area) %>%
  group_by(region, area) %>%
  summarise(num_fires = n()) %>%
  mutate(fires_sqmile = num_fires / area) %>%
  arrange(desc(fires_sqmile))
`summarise()` regrouping output by 'region' (override with `.groups` argument)

This table shows Puerto Rico has the highest proportion of fires compared to its size, followed by New Jersey in the NE of the country and finally by the States in the SE of the country.

fires_states %>%
  select(region, area) %>%
  group_by(region, area) %>%
  summarise(num_fires = n()) %>%
  mutate(fires_sqmile = num_fires / area) %>%
  right_join(state_map, by = "region") %>%
  ggplot +
  (aes(x = long, y = lat, group = group, fill = fires_sqmile)) + 
  geom_polygon() + 
  geom_path(color = "white") + 
  scale_fill_distiller(name = "Fire per Sq Mile", palette = "PuBuGn") +
  theme_map() + 
  coord_map("mollweide") + 
  ggtitle(paste0("Total US Wildfires per Square Mile from 1992-2015")) + 
  theme(plot.title = element_text(hjust = 0.5))
`summarise()` regrouping output by 'region' (override with `.groups` argument)

Puerto Rico is not shown on this map, but visually we can see the data for the other 51 entries, and the south eastern states still have the highest proportion of wildfires. Interestingly New Jersey also shows has a hotspot in the NE of the country.

Do causes change over time?

Splitting causes into 2 group for legibility.

The first group is for directly man created fires.

fires_states %>%
  select(stat_cause_descr, fire_year) %>%
  group_by(fire_year, stat_cause_descr) %>%
  filter(stat_cause_descr == "Arson" | stat_cause_descr == "Campfire" |
           stat_cause_descr == "Children" | stat_cause_descr == "Equipment Use" |
           stat_cause_descr == "Fireworks" | stat_cause_descr == "Smoking") %>%
  summarise(num_fires = n()) %>%
  ggplot +
  aes(x = fire_year, y = num_fires, colour = stat_cause_descr) +
  geom_line() +
  ggtitle("Amount of fires by cause, for years 1992-2015\n") + 
  xlab("\nYear") +
  ylab("Number of Fires\n") +
  labs(colour = "Cause of fire") +
  theme_bw() +
  theme(plot.title = element_text(hjust = 0.5))
`summarise()` regrouping output by 'fire_year' (override with `.groups` argument)

The 2 large peaks in Arson are obvious in 1999 and 2006. There was a large heatwave in 2006, but I’m not sure why this would result in an increase in arson. Perhaps there wasn’t an actual increase in the amount of arson, but it could have been due to the heatwave making the ground drier than normal creating extra fuel to aid the spread of fires that would have normally not resulted in a large scale fire. This may also be the same reason that there is also another peak in 2006 for Equipment Use. Arson however does look to be decreasing since 2006, as does children. Other wise most of the other causes of wildfires seem to be reasonably stable. Perhaps we shall try modelling arson and children related fires to see if we can identify a general trend.

And this one for natural occuring fires.

fires_states %>%
  select(stat_cause_descr, fire_year) %>%
  group_by(fire_year, stat_cause_descr) %>%
  filter(stat_cause_descr == "Debris Burning" | stat_cause_descr == "Lightning" |
           stat_cause_descr == "Miscellaneous" | stat_cause_descr == 
           "Missing/Undefined" | stat_cause_descr == "Powerline" | 
           stat_cause_descr == "Railroad" | stat_cause_descr == "Structure") %>%
  summarise(num_fires = n()) %>%
  ggplot +
  aes(x = fire_year, y = num_fires, colour = stat_cause_descr) +
  geom_line() +
  ggtitle("Amount of fires by cause, for years 1992-2015\n") + 
  xlab("\nYear") +
  ylab("Number of Fires\n") +
  labs(colour = "Cause of fire") +
  theme_bw() +
  theme(plot.title = element_text(hjust = 0.5))
`summarise()` regrouping output by 'fire_year' (override with `.groups` argument)

Similar peaks can be seen in Debris, Miscellaneous and lightning in the heatwave of 2006 that left the ground very dry. There are peaks from 1997 to 2003 in debris, miscellaneous and lightening, but also a trough in missing/undefined, so this is likely to be due to more accurate classification of fires and not using the missing/undefined category as much.

Difference in causes between states

state_map_southern <- state_map %>%
  filter(region == "florida" | region == "georgia" | region == "alabama" |
           region == "mississippi" | region == "south carolina" | 
           region == "north carolina" | region == "tennessee" | 
           region == "arkansas" | region == "louisiana")
fires_states %>%
  filter(fire_year == "1992" | fire_year == "1993" | fire_year == "1994" |
           fire_year == "1995") %>%
  filter(region == "florida" | region == "georgia" | region == "alabama" |
           region == "mississippi" | region == "south carolina" | 
           region == "north carolina" | region == "tennessee" |
           region == "arkansas" | region == "louisiana") %>%
  select(region, stat_cause_descr) %>%
  group_by(region, stat_cause_descr) %>%
  summarise(num_fire = n()) %>%
  top_n(1) %>%
  right_join(state_map_southern, by = "region") %>%
  ggplot +
  (aes(x = long, y = lat, group = group, fill = stat_cause_descr)) + 
  geom_polygon() + 
  geom_path(color = "white") + 
  theme_map() + 
  scale_fill_brewer(name = "Cause of Fires", palette = "PuBuGn") +
  ggtitle("Total US Wildfires main cause from 1992-1995") + 
  theme(plot.title = element_text(hjust = 0.5))
`summarise()` regrouping output by 'region' (override with `.groups` argument)
Selecting by num_fire

fires_states %>%
  filter(fire_year == "1996" | fire_year == "1997" | fire_year == "1998" |
           fire_year == "1999") %>%
  filter(region == "florida" | region == "georgia" | region == "alabama" |
           region == "mississippi" | region == "south carolina" | 
           region == "north carolina" | region == "tennessee" |
           region == "arkansas" | region == "louisiana") %>%
  select(region, stat_cause_descr) %>%
  group_by(region, stat_cause_descr) %>%
  summarise(num_fire = n()) %>%
  top_n(1) %>%
  right_join(state_map_southern, by = "region") %>%
  ggplot +
  (aes(x = long, y = lat, group = group, fill = stat_cause_descr)) + 
  geom_polygon() + 
  geom_path(color = "white") + 
  theme_map() + 
  scale_fill_brewer(name = "Cause of Fires", palette = "PuBuGn") +
  ggtitle("Total US Wildfires main cause from 1996-1999") + 
  theme(plot.title = element_text(hjust = 0.5))
`summarise()` regrouping output by 'region' (override with `.groups` argument)
Selecting by num_fire

fires_states %>%
  filter(fire_year == "2000" | fire_year == "2001" | fire_year == "2002" |
           fire_year == "2003") %>%
  filter(region == "florida" | region == "georgia" | region == "alabama" |
           region == "mississippi" | region == "south carolina" | 
           region == "north carolina" | region == "tennessee" |
           region == "arkansas" | region == "louisiana") %>%
  select(region, stat_cause_descr) %>%
  group_by(region, stat_cause_descr) %>%
  summarise(num_fire = n()) %>%
  top_n(1) %>%
  right_join(state_map_southern, by = "region") %>%
  ggplot +
  (aes(x = long, y = lat, group = group, fill = stat_cause_descr)) + 
  geom_polygon() + 
  geom_path(color = "white") + 
  theme_map() + 
  scale_fill_brewer(name = "Cause of Fires", palette = "PuBuGn") +
  ggtitle("Total US Wildfires main cause from 2000-2003") + 
  theme(plot.title = element_text(hjust = 0.5))
`summarise()` regrouping output by 'region' (override with `.groups` argument)
Selecting by num_fire

fires_states %>%
  filter(fire_year == "2004" | fire_year == "2005" | fire_year == "2006" |
           fire_year == "2007") %>%
  filter(region == "florida" | region == "georgia" | region == "alabama" |
           region == "mississippi" | region == "south carolina" | 
           region == "north carolina" | region == "tennessee" |
           region == "arkansas" | region == "louisiana") %>%
  select(region, stat_cause_descr) %>%
  group_by(region, stat_cause_descr) %>%
  summarise(num_fire = n()) %>%
  top_n(1) %>%
  right_join(state_map_southern, by = "region") %>%
  ggplot +
  (aes(x = long, y = lat, group = group, fill = stat_cause_descr)) + 
  geom_polygon() + 
  geom_path(color = "white") + 
  theme_map() + 
  scale_fill_brewer(name = "Cause of Fires", palette = "PuBuGn") +
  ggtitle("Total US Wildfires main cause from 2004-2007") + 
  theme(plot.title = element_text(hjust = 0.5))
`summarise()` regrouping output by 'region' (override with `.groups` argument)
Selecting by num_fire

fires_states %>%
  filter(fire_year == "2008" | fire_year == "2009" | fire_year == "2010" |
           fire_year == "2011") %>%
  filter(region == "florida" | region == "georgia" | region == "alabama" |
           region == "mississippi" | region == "south carolina" | 
           region == "north carolina" | region == "tennessee" |
           region == "arkansas" | region == "louisiana") %>%
  select(region, stat_cause_descr) %>%
  group_by(region, stat_cause_descr) %>%
  summarise(num_fire = n()) %>%
  top_n(1) %>%
  right_join(state_map_southern, by = "region") %>%
  ggplot +
  (aes(x = long, y = lat, group = group, fill = stat_cause_descr)) + 
  geom_polygon() + 
  geom_path(color = "white") + 
  theme_map() + 
  scale_fill_brewer(name = "Cause of Fires", palette = "PuBuGn") +
  ggtitle("Total US Wildfires main cause from 2008-2011") + 
  theme(plot.title = element_text(hjust = 0.5))
`summarise()` regrouping output by 'region' (override with `.groups` argument)
Selecting by num_fire

fires_states %>%
  filter(fire_year == "2012" | fire_year == "2013" | fire_year == "2014" |
           fire_year == "2015") %>%
  filter(region == "florida" | region == "georgia" | region == "alabama" |
           region == "mississippi" | region == "south carolina" | 
           region == "north carolina" | region == "tennessee" |
           region == "arkansas" | region == "louisiana") %>%
  select(region, stat_cause_descr) %>%
  group_by(region, stat_cause_descr) %>%
  summarise(num_fire = n()) %>%
  top_n(1) %>%
  right_join(state_map_southern, by = "region") %>%
  ggplot +
  (aes(x = long, y = lat, group = group, fill = stat_cause_descr)) + 
  geom_polygon() + 
  geom_path(color = "white") + 
  theme_map() + 
  scale_fill_brewer(name = "Cause of Fires", palette = "PuBuGn") +
  ggtitle("Total US Wildfires main cause from 2012-2015") + 
  theme(plot.title = element_text(hjust = 0.5))
`summarise()` regrouping output by 'region' (override with `.groups` argument)
Selecting by num_fire

Looking at these trends some interesting insights can be seen. For the combined years data Florida stands out as having railroad as its main cause of wildfire, but from the above plots it can be seen that these railroad fires are only the main cause up to the 4 yearly period ending in 2003 and then the main cause changes to lightning until the end of the collection period in 2015. Similarly arson seem reasonably popular in the southern states until 2007, when it no longer appears as the most common cause of wildfire. This downward trend was also noted earlier in the overall causation plots for all states

The railroad fires in Florida are quite interesting considering that other southern states have more woodland or open pastures that I thought would have been more suseptible to fire. I’m going to try and more closely map railroad fires in Florida itself.

fires_states %>%
  dplyr::filter(region == "florida" & stat_cause_descr == "Railroad" & 
           fire_year == "1992") %>%
  leaflet() %>%
  addTiles() %>%
  addMarkers(lng = ~longitude, lat = ~latitude, label =
               ~paste("Fire Size: ", fire_size, "/ Month: ", discovery_moy))

There is something not right with this data, it is extremely unlikely that all these fire are from railroads . So I’m going to check another random year in 1998.

fires_states %>%
  dplyr::filter(region == "florida" & stat_cause_descr == "Railroad" & 
           fire_year == "1998") %>%
  leaflet() %>%
  addTiles() %>%
  addMarkers(lng = ~longitude, lat = ~latitude, label =
               ~paste("Fire Size: ", fire_size, "/ Month: ", discovery_moy))

The same issue is present, there is definitely something wrong here. Let’s check some more years.

fires_states %>%
  dplyr::filter(region == "florida" & stat_cause_descr == "Railroad" & 
           fire_year == "2008") %>%
  leaflet() %>%
  addTiles() %>%
  addMarkers(lng = ~longitude, lat = ~latitude, label =
               ~paste("Fire Size: ", fire_size, "/ Month: ", discovery_moy))

Now that is much better, with a lot less fires occurring and all of them next to a railroad as you would expect. Let’s check another year.

fires_states %>%
  dplyr::filter(region == "florida" & stat_cause_descr == "Railroad" & 
           fire_year == "2015") %>%
  leaflet() %>%
  addTiles() %>%
  addMarkers(lng = ~longitude, lat = ~latitude, label =
               ~paste("Fire Size: ", fire_size, "/ Month: ", discovery_moy))

2015’s data looks the same as 2008 and what I would expect for railroad fires, occurring next to rails and being few and far between!

Having used leaflet to plot all the Lat/long coordinates for the railroad fires in 1992, 1998, 2008 and 2015, I am doubtful of the validity of either the recorded classification of fire origin or the accuracy of the coordinates in the earlier years of the recording period. The majority of plotted fires have been started many miles away from any railroad. This is especially obvious for the 2 fires that occurred near Key West in 1992, which has no rail links anywhere near by only road. The coordinates have been given to 5 decimal places, which allows a precision of 1.1 meters, so unless they have been entered into the database incorrectly I think it is probably far more likely that an incorrect cause descriptor may have been entered for a lot of fires in the earlier years. This error seems to have been rectified in the later years of the dataset, as can be seen in the 2008 and 2015 data behaving as expected as above.

Correlation between states and fire size

fires_states %>%
  select(region, fire_size_class) %>%
  group_by(region, fire_size_class) %>%
  summarise(num_fire = n()) %>%
  top_n(1) %>%
  right_join(state_map, by = "region") %>%
  ggplot +
  (aes(x = long, y = lat, group = group, fill = fire_size_class)) +
  geom_polygon() +
  geom_path(color = "white") +
  theme_map() +
  scale_fill_brewer(name = "Fire Size Class", palette = "PuBuGn") +
  ggtitle("Most common wildfire size per State 1992-2015") +
  theme(plot.title = element_text(hjust = 0.5))
`summarise()` regrouping output by 'region' (override with `.groups` argument)
Selecting by num_fire

fires_states %>%
  select(region, fire_size_class) %>%
  filter(fire_size_class == "G") %>%
  group_by(region) %>%
  summarise(num_fire = n()) %>%
  right_join(state_map, by = "region") %>%
  ggplot +
  (aes(x = long, y = lat, group = group, fill = num_fire)) +
  geom_polygon() +
  geom_path(color = "white") +
  theme_map() +
  scale_fill_distiller(name = "Number of Fires", palette = "PuBuGn") +
  ggtitle("Number of large class G fires per State 1992-2015") +
  theme(plot.title = element_text(hjust = 0.5))
`summarise()` ungrouping output (override with `.groups` argument)

From the plots we can see that the Western states have the most small fires and also the most large fires! Not entirely the most helpful plots…

Are fires more prevalent in certain months for individual states

fires_states %>%
  dplyr::select(region, discovery_moy) %>%
  group_by(region, discovery_moy) %>%
  summarise(num_fire = n()) %>%
  top_n(1) %>%
  right_join(state_map, by = "region") %>%
  ggplot +
  (aes(x = long, y = lat, group = group, fill = discovery_moy)) +
  geom_polygon() +
  geom_path(color = "white") +
  theme_map() +
  scale_fill_brewer(name = "Months of Year", palette = "PuBuGn") +
  ggtitle("Months with most fires per State 1992-2015") +
  theme(plot.title = element_text(hjust = 0.5))
`summarise()` regrouping output by 'region' (override with `.groups` argument)
Selecting by num_fire

fires_states %>%
  filter(fire_year == "1992" | fire_year == "1993" | fire_year == "1994" |
           fire_year == "1995") %>%
  select(region, discovery_moy) %>%
  group_by(region, discovery_moy) %>%
  summarise(num_fire = n()) %>%
  top_n(1) %>%
  right_join(state_map, by = "region") %>%
  ggplot +
  (aes(x = long, y = lat, group = group, fill = discovery_moy)) +
  geom_polygon() +
  geom_path(color = "white") +
  theme_map() +
  scale_fill_brewer(name = "Months of Year", palette = "PuBuGn") +
  ggtitle("Month with most fires per State 1992-1995") +
  theme(plot.title = element_text(hjust = 0.5)) 
`summarise()` regrouping output by 'region' (override with `.groups` argument)
Selecting by num_fire

  # theme(legend.position = "left")
fires_states %>%
  filter(fire_year == "1996" | fire_year == "1997" | fire_year == "1998" |
           fire_year == "1999") %>%
  select(region, discovery_moy) %>%
  group_by(region, discovery_moy) %>%
  summarise(num_fire = n()) %>%
  top_n(1) %>%
  right_join(state_map, by = "region") %>%
  ggplot +
  (aes(x = long, y = lat, group = group, fill = discovery_moy)) +
  geom_polygon() +
  geom_path(color = "white") +
  theme_map() +
  scale_fill_brewer(name = "Months of Year", palette = "PuBuGn") +
  ggtitle("Month with most fires per State 1996-1999") +
  theme(plot.title = element_text(hjust = 0.5))
`summarise()` regrouping output by 'region' (override with `.groups` argument)
Selecting by num_fire

fires_states %>%
  filter(fire_year == "2000" | fire_year == "2001" | fire_year == "2002" |
           fire_year == "2003") %>%
  select(region, discovery_moy) %>%
  group_by(region, discovery_moy) %>%
  summarise(num_fire = n()) %>%
  top_n(1) %>%
  right_join(state_map, by = "region") %>%
  ggplot +
  (aes(x = long, y = lat, group = group, fill = discovery_moy)) +
  geom_polygon() +
  geom_path(color = "white") +
  theme_map() +
  scale_fill_brewer(name = "Months of Year", palette = "PuBuGn") +
  ggtitle("Month with most fires per State 2000-2003") +
  theme(plot.title = element_text(hjust = 0.5))
`summarise()` regrouping output by 'region' (override with `.groups` argument)
Selecting by num_fire

fires_states %>%
  filter(fire_year == "2004" | fire_year == "2005" | fire_year == "2006" |
           fire_year == "2007") %>%
  select(region, discovery_moy) %>%
  group_by(region, discovery_moy) %>%
  summarise(num_fire = n()) %>%
  top_n(1) %>%
  right_join(state_map, by = "region") %>%
  ggplot +
  (aes(x = long, y = lat, group = group, fill = discovery_moy)) +
  geom_polygon() +
  geom_path(color = "white") +
  theme_map() +
  scale_fill_brewer(name = "Months of Year", palette = "PuBuGn") +
  ggtitle("Month with most fires per State 2004-2007") +
  theme(plot.title = element_text(hjust = 0.5))
`summarise()` regrouping output by 'region' (override with `.groups` argument)
Selecting by num_fire

fires_states %>%
  filter(fire_year == "2008" | fire_year == "2009" | fire_year == "2010" |
           fire_year == "2011") %>%
  select(region, discovery_moy) %>%
  group_by(region, discovery_moy) %>%
  summarise(num_fire = n()) %>%
  top_n(1) %>%
  right_join(state_map, by = "region") %>%
  ggplot +
  (aes(x = long, y = lat, group = group, fill = discovery_moy)) +
  geom_polygon() +
  geom_path(color = "white") +
  theme_map() +
  scale_fill_brewer(name = "Months of Year", palette = "PuBuGn") +
  ggtitle("Month with most fires per State 2008-2011") +
  theme(plot.title = element_text(hjust = 0.5))
`summarise()` regrouping output by 'region' (override with `.groups` argument)
Selecting by num_fire

fires_states %>%
  filter(fire_year == "2012" | fire_year == "2013" | fire_year == "2014" |
           fire_year == "2015") %>%
  select(region, discovery_moy) %>%
  group_by(region, discovery_moy) %>%
  summarise(num_fire = n()) %>%
  top_n(1) %>%
  right_join(state_map, by = "region") %>%
  ggplot +
  (aes(x = long, y = lat, group = group, fill = discovery_moy)) +
  geom_polygon() +
  geom_path(color = "white") +
  theme_map() +
  scale_fill_brewer(name = "Months of Year", palette = "PuBuGn") +
  ggtitle("Month with most fires per State 2012-2015") +
  theme(plot.title = element_text(hjust = 0.5))
`summarise()` regrouping output by 'region' (override with `.groups` argument)
Selecting by num_fire

The above plots are quite interesting. The months of the year that have the most seems to widely change in certain state. Mainly the east half of the country have the most fires in the Spring (Feb-May) and the western part of the country have the most fires later on in Summer and Fall (Jun-Oct). There are however a few exceptions that can be seen in the 2004-2007 and 2008-2011 data Texas has the most fires in January. Florida also mostly conformed to the East/West split with the majority of its worst months for fires taking place in March or April up until 2007, then the most common month moves later into June and July for the rest of the reporting period until 2015. This may have to due with main cause of fires in Florida changing from railroad to lightning related about the same time, as we noted earlier on when looking at causation. As July is the main month for tropical storms and lightning in Florida this is a possible cause for the highest month becoming later in the year than before. (2)

  1. https://www.weather.gov/mlb/fl_lightning_climo
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3J9CmxpYnJhcnkoUlNRTGl0ZSkKbGlicmFyeShkYnBseXIpCmxpYnJhcnkoamFuaXRvcikKbGlicmFyeShsdWJyaWRhdGUpCmxpYnJhcnkoZGF0YXNldHMpCmxpYnJhcnkoZ2d0aGVtZXMpCmxpYnJhcnkoZ2dhbmltYXRlKQpsaWJyYXJ5KG1vZGVscikKbGlicmFyeShicm9vbSkKbGlicmFyeShnZ2ZvcnRpZnkpCmxpYnJhcnkoaW5mZXIpCmxpYnJhcnkoTUFTUykKbGlicmFyeSh0c2VyaWVzKQpsaWJyYXJ5KGZvcmVjYXN0KQpsaWJyYXJ5KGZhYmxlKQpsaWJyYXJ5KGZhYmxldG9vbHMpCmxpYnJhcnkodHNpYmJsZSkKbGlicmFyeSh0c2liYmxlZGF0YSkKbGlicmFyeShmZWFzdHMpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGxlYWZsZXQpCmBgYAoKCgojIDIuIENyZWF0aW5nIHNvbWUgaW5pdGlhbCB2aXN1YWxpc2F0aW9ucwoKCiMjIyBGaXJlcyBwZXIgeWVhcgoKYGBge3J9CnllYXJfcGxvdCA8LSBmaXJlc19zbWFsbCAlPiUKICBncm91cF9ieShmaXJlX3llYXIpICU+JQogIHN1bW1hcmlzZShudW1fZmlyZXMgPW4oKSkKCnllYXJfcGxvdCAlPiUKICBnZ3Bsb3QgKwogIGFlcyh4ID0gZmlyZV95ZWFyLCB5ID0gbnVtX2ZpcmVzKSArCiAgZ2VvbV9wb2ludCgpICsKICBnZW9tX2xpbmUoKSArCiAgeWxpbSgwLCAxMjAwMDApICsKICBnZ3RpdGxlKCJBbW91bnQgb2YgZmlyZXMgcGVyIHllYXIgMTk5Mi0yMDE1XG4iKSArIAogIHhsYWIoIlxuWWVhciIpICsKICB5bGFiKCJOdW1iZXIgb2YgRmlyZXNcbiIpICsKICB0aGVtZV9idygpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKCmBgYAoKKipUaGVyZSBpcyBhIGxvdCBvZiB2YXJpYXRpb24gaW4gdGhlIGRhdGEgYmV0d2VlbiB5ZWFycy4gIFZpc3VhbGx5IGl0IGxvb2tzIGxpa2UgYSByZXBlYXRpbmcgcGF0dGVybiBpcyBvY2N1cnJpbmcgZXZlcnkgNSB5ZWFycyBvciBzbyB3aXRoIDQgcGVha3MgdmlzaWJsZSB3aXRoaW4gdGhpcyByZXBvcnRpbmcgcGVyaW9kLiAgSGF2aW5nIGxvb2tlZCBhdCB0aGUgaGlzdG9yaWMgd2VhdGhlciBmb3IgdGhhdCBkYXRlIHJhbmdlIHRoZXNlIHBlYWtzIHNlZW1zIHRvIGNvaW5jaWRlIHdpdGggcmVjb3JkZWQgaGVhdHdhdmVzIGluIDIwMDAsIDIwMDYgYW5kIDIwMTEuKDEpKioKCmh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0xpc3Rfb2ZfaGVhdF93YXZlcwoKCiMjIyMgSSB3aWxsIHRyeSB0byBjcmVhdGUgYSBsaW5lYXIgbW9kZWwgdG8gaG9wZWZ1bGx5IHNob3cgYW55IGluY3JlYXNlIG9yIGRlY3JlYXNlIG9mIGZpcmVzIG92ZXIgdGltZSAoc2VlIHNlcGVyYXRlIHdvcmtib29rKS4gIEFzIHRoaXMgaXMgdGltZSBzZXJpZXMgZGF0YSBhIGxpbmVhciBtb2RlbCB3aWxsIG5vdCBmaXQsIGJ1dCBpdCBjb3VsZCBiZSBpbnRlcmVzdGluZyB0byBzZWUgaWYgaXQgaWRlbnRpZmllcyBhIGdlbmVyYWwgdW5kZXJseWluZyB0cmVuZC4KCgoKCiMjIyBGaXJlcyBwZXIgbW9udGgKCmBgYHtyfQpmaXJlc19zbWFsbCAlPiUKICBtdXRhdGUoeWVhcl9tb250aCA9IG1ha2VfZGF0ZShmaXJlX3llYXIsIGRpc2NvdmVyeV9tb3kpKSAlPiUKICBncm91cF9ieSh5ZWFyX21vbnRoKSAlPiUKICBzdW1tYXJpc2UobnVtX2ZpcmVzID0gbigpKSAlPiUKICBnZ3Bsb3QgKwogIGFlcyh4ID0geWVhcl9tb250aCwgeSA9IG51bV9maXJlcykgKwogIGdlb21fbGluZShjb2wgPSAiZGFyayBibHVlIikgKwogIGdndGl0bGUoIkFtb3VudCBvZiBmaXJlcyBwZXIgbW9udGggMTk5Mi0yMDE1XG4iKSArIAogIHhsYWIoIlxuWWVhciIpICsKICB5bGFiKCJOdW1iZXIgb2YgRmlyZXNcbiIpICsKICB0aGVtZV9idygpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKYGBgCgoqKlBlYWtzIGFyZSBzdGlsbCBzaG93biB0byBiZSBvY2N1cnJpbmcgaW4gdGhlIHN1bW1lcnMuIFRoZSAyMDA2IGhlYXR3YXZlIGlzIGVzcGVjaWFsbHkgdmlzaWJsZS4qKgoKCgojIyMgVXNpbmcgdGhlIFNBUklNQSBtb2RlbC4KCmBgYHtyfQptb250aGx5IDwtIGZpcmVzX3NtYWxsICU+JQogIG11dGF0ZSh5ZWFyX21vbnRoID0gbWFrZV9kYXRlKGZpcmVfeWVhciwgZGlzY292ZXJ5X21veSkpICU+JQogIGdyb3VwX2J5KHllYXJfbW9udGgpICU+JQogIHN1bW1hcmlzZShudW1fZmlyZXMgPSBuKCkpCgp3cml0ZV9jc3YobW9udGhseSwgcGF0aCA9ICJjbGVhbl9kYXRhL21vbnRobHkuY3N2IikKCm1vbnRobHkKYGBgCgoqKkNvbnRpbnVlZCBvbiBzZXBlcmF0ZSB3b3Jrc2hlZXQqKgoKCgoKIyMjIEZpcmVzIHBlciBkYXkKCmBgYHtyfQpmaXJlc19zbWFsbCAlPiUKICBncm91cF9ieShkaXNjb3ZlcnlfZGF0ZSkgJT4lCiAgc3VtbWFyaXNlKG51bV9maXJlcyA9IG4oKSkgJT4lCiAgZ2dwbG90ICsKICBhZXMoeCA9IGRpc2NvdmVyeV9kYXRlLCB5ID0gbnVtX2ZpcmVzKSArCiAgZ2VvbV9saW5lKGNvbCA9ICJkYXJrIGJsdWUiKSArCiAgZ2d0aXRsZSgiQW1vdW50IG9mIGZpcmVzIHBlciBkYXkgMTk5Mi0yMDE1XG4iKSArIAogIHhsYWIoIlxuWWVhciIpICsKICB5bGFiKCJOdW1iZXIgb2YgRmlyZXNcbiIpICsKICB0aGVtZV9idygpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKCmBgYAoKKipUaGlzIHNob3dzIGEgdHlwaWNhbCB0aW1lIHNlcmllcyBwbG90IHdpdGggYSBjeWNsaWMgdmFyaWF0aW9uIGR1ZSB0byB3YXJtZXIgd2VhdGhlciBpbiB0aGUgc3VtbWVyIHRpbWUuKioKCgoKCgojIyMgRmlyZXMgYnkgZGF5IG9mIHllYXIKCgpgYGB7cn0KZmlyZXNfc21hbGwgJT4lCiAgZ3JvdXBfYnkoZGlzY292ZXJ5X2RveSkgJT4lCiAgc3VtbWFyaXNlKG51bV9maXJlcyA9IG4oKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZGlzY292ZXJ5X2RveSwgeSA9IG51bV9maXJlcykpICsKICBnZW9tX2xpbmUoY29sID0gImRhcmsgYmx1ZSIpICsKICBnZ3RpdGxlKCJBbW91bnQgb2YgZmlyZXMgcGVyIGRheSBvZiB5ZWFyLCBmb3IgY29tYmluZWQgeWVhcnMgMTk5Mi0yMDE1XG4iKSArIAogIHhsYWIoIlxuRGF5IG9mIFllYXIiKSArCiAgeWxhYigiTnVtYmVyIG9mIEZpcmVzXG4iKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCmBgYAoKCioqVGhlIGFyZSBwZWFrcyBhcm91bmQgZGF5IDYwLTExMCBhbmQgYSBiaWcgcGVhayBhcm91bmQgMTgwLioqCgojIyMjIENoZWNraW5nIHRoZSBkYXRhIHRvIHNlZSBleGFjdGx5IHdoZXJlIHRoZSBwZWFrIG9jY3VycwoKYGBge3J9CmZpcmVzX3NtYWxsICU+JQogIGdyb3VwX2J5KGRpc2NvdmVyeV9kb3kpICU+JQogIHN1bW1hcmlzZShudW1fZmlyZXMgPSBuKCkpICU+JQogIGFycmFuZ2UoZGVzYyhudW1fZmlyZXMpKQpgYGAKKipUaGUgMiBoaWdoZXN0IGRheXMgb2YgdGhlIHllYXIgYXJlIG9uIDE4NSBhbmQgMTg2LCB3aGljaCBoYXBwZW5zIHRvIGJlIEluZGVwZW5kZW5jZSBEYXkgKDR0aCBKdWx5KSBvbiBhIG5vcm1hbCB5ZWFyIGFuZCBhIGxlYXAgeWVhciByZXRyb3NwZWN0aXZlbHkuICBTbyBJIGltYWdpbmUgbW9zdCBvZiB0aGUgZXh0cmEgZmlyZXMgKGxpdGVyYWxseSBvdmVyIGRvdWJsZSB0aGUgbm9ybWFsIGFtb3VudCkgYXJlIGNhdXNlZCBieSBmaXJld29ya3MuKioKCgoKIyMjIEZpcmVzIGJ5IG1vbnRoIG9mIHllYXIKCmBgYHtyfQpmaXJlc19zbWFsbCAlPiUKICBncm91cF9ieShkaXNjb3ZlcnlfbW95KSAlPiUKICBzdW1tYXJpc2UobnVtX2ZpcmVzID0gbigpKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBkaXNjb3ZlcnlfbW95LCB5ID0gbnVtX2ZpcmVzKSkgKwogIGdlb21fY29sKGZpbGwgPSAiZGFyayBibHVlIiwgY29sID0gImJsYWNrIikgKwogIGdndGl0bGUoIkFtb3VudCBvZiBmaXJlcyBwZXIgbW9udGggb2YgeWVhciwgZm9yIGNvbWJpbmVkIHllYXJzIDE5OTItMjAxNVxuIikgKyAKICB4bGFiKCJcbk1vbnRoIG9mIFllYXIiKSArCiAgeWxhYigiTnVtYmVyIG9mIEZpcmVzXG4iKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCmBgYAoKKipUaGVyZSBhcmUgMiBkZWZpbml0ZSBwZWFrcyBkdXJpbmcgdGhlIHllYXIuICBNYXJjaCBhbmQgQXByaWwgYXJlIHBvc3NpYmx5IGR1ZSB0byB0aGUgVVMgIlNwcmluZyBCcmVhayIsIHdoZXJlIHNjaG9vbHMgYW5kIFVuaXZlcnNpdGllcyBhcmUgc3RvcHBlZCBhbmQgc28gZmFtaWxpZXMgYXJlIGxpa2VseSB0byBiZSBvbiB2YWNhdGlvbiBkdXJpbmcgdGhhdCBwZXJpb2QgcG9zc2libHkgdmlzaXRpbmcgTmF0aW9uYWwgUGFya3MuICBKdWx5IGFuZCBBdWd1c3QgaXMgYWxzbyBTdW1tZXIgQnJlYWsgZm9yIHNjaG9vbCB3aXRoIGJvdGggZmFtaWxpZXMgdmlzaXRpbmcgUGFya3MgYW5kIGhvdCB3ZWF0aGVyIGxpa2VseSBjYXVzZXMgb2YgZmlyZSBvdXRicmVha3MuICBJIHdpbGwgaGF2ZSBhIGxvb2sgYXQgdGhlIGRhdGEgYW5kIHNlZSBpZiB0aGVyZSBpcyBhbnl0aGluZyByZWxhdGVkIHRvIHZhY2F0aW9uIHRpbWUgdGhhdCBjb3VsZCBjb3Jyb2JvcmF0ZSB0aGlzLioqCgoKaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvU2Nob29sX2hvbGlkYXlzX2luX3RoZV9Vbml0ZWRfU3RhdGVzCgoKCmBgYHtyfQptYXJfYXByX2NhdXNlcyA8LSBmaXJlc19zbWFsbCAlPiUKICBkcGx5cjo6ZmlsdGVyKGRpc2NvdmVyeV9tb3kgPT0gIk1hciIgfCBkaXNjb3ZlcnlfbW95ID09ICJBcHJpbCIpICU+JQogIGdyb3VwX2J5KHN0YXRfY2F1c2VfZGVzY3IpICU+JQogIHN1bW1hcmlzZShudW1fZmlyZXNfbWFyX2FwciA9IG4oKSkgJT4lCiAgYXJyYW5nZShkZXNjKG51bV9maXJlc19tYXJfYXByKSkKICAKYGBgCgpgYGB7cn0KbWF5X2p1bmVfY2F1c2VzIDwtIGZpcmVzX3NtYWxsICU+JQogIGRwZmlsdGVyKGRpc2NvdmVyeV9tb3kgPT0gIk1heSIgfCBkaXNjb3ZlcnlfbW95ID09ICJKdW5lIikgJT4lCiAgZ3JvdXBfYnkoc3RhdF9jYXVzZV9kZXNjcikgJT4lCiAgc3VtbWFyaXNlKG51bV9maXJlc19tYXlfanVuZSA9IG4oKSkgJT4lCiAgYXJyYW5nZShkZXNjKG51bV9maXJlc19tYXlfanVuZSkpCmBgYAoKYGBge3J9Cm1hcl9hcHJfY2F1c2VzJG51bV9maXJlc19tYXlfanVuZSA8LSBtYXlfanVuZV9jYXVzZXMkbnVtX2ZpcmVzX21heV9qdW5lCgptYXJfYXByX2NhdXNlcwpgYGAKCioqQWx0aG91Z2ggdGhlcmUgaXMgYSBsYXJnZSBpbmNyZWFzZSBpbiBmaXJlcyBkdWUgdG8gZGVicmlzIGJ1cm5pbmcsIGFyc29uIGFuZCBtaXNjZWxsYW5lb3VzIGluIE1hcmNoIGFuZCBBcHJpbCwgaW4gTWF5IGFuZCBKdW5lIHRoZSBudW1iZXIgb2YgZmlyZXMgYnkgY2hpbGRyZW4sIGNhbXBmaXJlIGFuZCBzbW9raW5nIGlzIGFsbCBoaWdoZXIgc28gdGhlcmUgaXMgbm8gZGVmaW5pdGUgcHJvb2YgdGhhdCBzY2hvb2wgYnJlYWtzIGFyZSB0byBjYXVzZSBmb3IgdGhlIHNwaWtlcyBpbiBNYXJjaCBhbmQgQXByaWwgZWFjaCB5ZWFyIG92ZXIgdGhlIHdob2xlIGRhdGEgcGVyaW9kLioqCgoKCgoKCgojIyMgRmlyZXMgYnkgY2F1c2UKCmBgYHtyfQpvcHRpb25zKHNjaXBlbiA9IDk5OSkKCmZpcmVzX3NtYWxsICU+JQogIGdyb3VwX2J5KHN0YXRfY2F1c2VfZGVzY3IpICU+JQogIHN1bW1hcmlzZShudW1fZmlyZXMgPSBuKCkpICU+JQogIGdncGxvdCArCiAgYWVzKHJlb3JkZXIoeCA9IHN0YXRfY2F1c2VfZGVzY3IsIG51bV9maXJlcyksIHkgPSBudW1fZmlyZXMpICsKICBnZW9tX2NvbChmaWxsID0gImRhcmsgYmx1ZSIpICsgCiAgY29vcmRfZmxpcCgpICsKICBnZ3RpdGxlKCJBbW91bnQgb2YgZmlyZXMgYnkgY2F1c2UsIGZvciBjb21iaW5lZCB5ZWFycyAxOTkyLTIwMTVcbiIpICsgCiAgeGxhYigiQ2F1c2Ugb2YgZmlyZVxuIikgKwogIHlsYWIoIlxuTnVtYmVyIG9mIEZpcmVzIikgKwogIHRoZW1lX2J3KCkgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQogIApgYGAKCgojIyMgRmlyZSBhdmcgc2l6ZSBieSBjYXVzZQoKYGBge3J9CmZpcmVzX3NtYWxsICU+JQogIGdyb3VwX2J5KHN0YXRfY2F1c2VfZGVzY3IpICU+JQogIHN1bW1hcmlzZShhdmdfc2l6ZSA9IG1lYW4oZmlyZV9zaXplKSkgJT4lCiAgZ2dwbG90ICsKICBhZXMocmVvcmRlcih4ID0gc3RhdF9jYXVzZV9kZXNjciwgYXZnX3NpemUpLCB5ID0gYXZnX3NpemUpICsKICBnZW9tX2NvbChmaWxsID0gImRhcmsgYmx1ZSIpICsgCiAgY29vcmRfZmxpcCgpICsKICBnZ3RpdGxlKCJBdmVyYWdlIHNpemUgb2YgZmlyZSBwZXIgY2F1c2UsIGZvciBjb21iaW5lZCB5ZWFycyAxOTkyLTIwMTVcbiIpICsgCiAgeGxhYigiQ2F1c2Ugb2YgZmlyZVxuIikgKwogIHlsYWIoIlxuU2l6ZSBvZiBmaXJlIChTcXVhcmUgTWlsZXMpIikgKwogIHRoZW1lX2J3KCkgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQpgYGAKCgojIyMgQXZnIGJ1cm4gdGltZSBieSBjYXVzZQoKYGBge3J9CmZpcmVzX3NtYWxsICU+JQogIHN1bW1hcmlzZShudW1fbmEgPSBzdW0oaXMubmEoY29udF9kYXRlKSkpCmBgYAoqTGl0ZXJhbGx5IGhhbGYgdGhlIGRhdGEgaXMgbWlzc2luZyBmb3IgYnVybiB0aW1lLCBtYWtpbmcgaXQgdmVyeSBkaWZmaWN1bHQgdG8gZG8gYW55IG1lYW5pbmdmdWwgYW5hbHlzaXMgc28gSSBzaGFsbCBub3QgY29uc2lkZXIgYnVybiB0aW1lIGF0IHRoaXMgdGltZS4qCgoKCiMjIyBGaXJlcyBieSBzaXplCgoKYGBge3J9CmZpcmVzX3NtYWxsICU+JQogIGdyb3VwX2J5KGZpcmVfc2l6ZV9jbGFzcykgJT4lCiAgc3VtbWFyaXNlKG51bV9maXJlcyA9IG4oKSkgJT4lCiAgZ2dwbG90ICsKICBhZXMoeCA9IGZpcmVfc2l6ZV9jbGFzcywgeSA9IG51bV9maXJlcywgZmlsbCA9IGZpcmVfc2l6ZV9jbGFzcykgKwogIGdlb21fY29sKGNvbCA9ICJibGFjayIpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjMDE2NDUwIiwgIiMwMjgxOGEiLCAiIzM2OTBjMCIsICIjNjdhOWNmIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIjYTZiZGRiIiwgIiNkMGQxZTYiLCIjZjZlZmY3IiksCiAgICAgICAgICAgICAgICAgICAgbmFtZSA9ICJGaXJlIFNpemUgQ2xhc3NpZmljYXRpb24iLAogICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IGMoIkEiLCAiQiIsICJDIiwgIkQiLCAiRSIsICJGIiwgIkciKSwKICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJBOiA8IDEvNCBhY3JlIiwgIkI6IDEvNCB0byAxMCBhY3JlcyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkM6IDEwIHRvIDEwMCBhY3JlcyIsICJEOiAxMDAgdG8gMzAwIGFjcmVzIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRTogMzAwIHRvIDEwMDAgYWNyZXMiLCAiRjogMTAwMCB0byA1MDAwIGFjcmVzIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRzogTW9yZSB0aGFuIDUwMDAgYWNyZXMiKSkgKwogIGdndGl0bGUoIkFtb3VudCBvZiBmaXJlcyB0eXBlcyBpbiB0aGUgeWVhcnMgMTk5Mi0yMDE1XG4iKSArIAogIHhsYWIoIlxuRmlyZSBTaXplIENsYXNzaWZpY2F0aW9uIikgKwogIHlsYWIoIk51bWJlciBvZiBGaXJlc1xuIikgKwogIHRoZW1lX2J3KCkgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKSAKICAKCmBgYAoKCgojIEdlbyBTcGF0aWFsIHdyYW5nbGluZyAKCgojIyMgVG8gbWFrZSBpdCBlYXNpZXIgdG8gdmlzdWFsbHkgZGV0ZWN0IGZyZXF1ZW5jeSBvZiB3aWxkZmlyZXMgYmV0d2VlbiBzdGF0ZXMgSSB3YW50IGRpc3BsYXkgaXQgaW4gYSBtYXAgZm9ybWF0LiAgQXMgSSdtIHVzaW5nIGdncGxvdDIgYWxyZWFkeSBJJ20gZ29pbmcgdG8gYWxzbyB1c2UgaXQgZm9yIG1hcHMgd2l0aCB0aGUgYGdlb21fcG9seWdvbigpYCwgYGNvb3JkX21hcCgpYCBhbG9uZyB3aXRoIHRoZSBnZ3RoZW1lcyBgdGhlbWVfbWFwKClgIGZ1bmN0aW9ucy4KCgojIyMjIEknbSBub3QgZW50aXJlbHkgc3VyZSB3aGF0IGdlby1zcGF0aWFsIGluZm9ybWF0aW9uIGlzIGJlaW5nIGhlbGQgd2l0aCBpbiB0aGUgc3FsaXRlIGRhdGFiYXNlIGZpbGUsIEkndmUgbWFkZSBhIGZldyBhdHRlbXB0cyB0byByZXRyaWV2ZSBpdCBidXQgaGF2ZSBiZWVuIHVuc3VjY2Vzc2Z1bC4gIFRoZXJlZm9yZSBJJ20gZ29pbmcgdG8gdXRlbGlzZSB0aGUgYGRhdGFzZXRzYCBwYWNrYWdlIHdoaWNoIGluY2x1ZGVzIHZhcmlvdXMgYml0cyBvZiBpbmZvcm1hdGlvbiBvbiB0aGUgVVMgU3RhdGVzLCBpbmNsdWRpbmcgY29vcmRpbmF0ZXMgZm9yIHN0YXRlIGJvdW5kYXJpZXMuCgoKYGBge3J9CiMgU3RhdGUgYm91bmRhcnkgY28tb3JkaW5hdGVzIGZyb20gJ2RhdGFzZXRzJyBwYWNrYWdlCgpzdGF0ZV9tYXAgPC0gbWFwX2RhdGEoInN0YXRlIikKc3RhdGVfbWFwCmBgYAoKCiMjIyMgQW5ub3lpbmdseSBpdCBkb2Vzbid0IGhhdmUgdGhlIGFiYnJldmlhdGlvbiBvZiB0aGUgU3RhdGUsIG9ubHkgdGhlIGZ1bGwgbmFtZSBzbyBJIG5lZWQgdG8gYWRkIHRoYXQgaW4uICBMdWNraWx5IHRoZSAnZGF0YXNldHMnIHBhY2thZ2UgYWxzbyBoYXMgYSB2ZWN0b3Igb2YgU3RhdGVzIG5hbWVzIGFuZCBhYmJyZXZpYXRpb25zIHNvIEkgc2hhbGwgbWFrZSBhIHRpYmJsZSB3aXRoIHRoZW0gYm90aCBpbi4KCgpgYGB7cn0Kc3RhdGUuYWJiCmBgYAoKYGBge3J9CnN0YXRlLm5hbWUKYGBgCgpgYGB7cn0Kc3RhdGVfbGlzdCA8LSB0aWJibGUoc3RhdGUgPSBzdGF0ZS5hYmIsIHN0YXRlX25hbWUgPSBzdGF0ZS5uYW1lKQpzdGF0ZV9saXN0CmBgYAoKCiMjIyMgVGhlIGBzdGF0ZV9tYXBgIGRhdGFmcmFtZSBpcyBpbiBsb3dlciBjYXNlIGFuZCBoYXMgdGhlIGNvbHVtbiBuYW1lICdyZWdpb24nLiAgSSBzaGFsbCBjaGFuZ2UgdGhlIGBzdGF0ZV9saXN0YCB0aWJibGUgdG8gYmUgdGhlIHNhbWUgZm9ybWF0IHNvIHRoZXkgY2FuIGJlIGpvaW5lZCB0b2dldGhlci4KCgpgYGB7cn0Kc3RhdGVfbGlzdCA8LSB0aWJibGUoc3RhdGUgPSBzdGF0ZS5hYmIsIHJlZ2lvbiA9IHRvbG93ZXIoc3RhdGUubmFtZSkpCmBgYAoKCiMjIyMgSm9pbmcgYHN0YXRlX2xpc3RgIHRvIGBmaXJlc19zbWFsbGAgZGF0YXNldHMKCmBgYHtyfQpmaXJlc19zdGF0ZXMgPC0gZmlyZXNfc21hbGwgJT4lCiAgbGVmdF9qb2luKHN0YXRlX2xpc3QsIGJ5ID0gInN0YXRlIikKCmZpcmVzX3N0YXRlcwpgYGAKCgojIyMjIENoZWNraW5nIHRoZSBqb2luIGhhcyB3b3JrZWQgYW5kIHRoZXJlIGFyZSBubyBtaXNzaW5nIHZhbHVlcy4KCmBgYHtyfQpmaXJlc19zdGF0ZXMgJT4lCiAgZmlsdGVyKGlzLm5hKHJlZ2lvbikpCmBgYAoKCiMjIyMgVGhlcmUgZG9lcyBzZWVtIHRvIGJlIDIyLDE0NyBOQXMgaW4gdGhlICdyZWdpb24nIGNvbHVtbiB3ZSBqdXN0IG1hZGUuICBTY3JvbGxpbmcgdGhyb3VnaCB0aGVyZSBhcmUgMiBtaXNzaW5nIFN0YXRlcyBvZiAnUFInIGFuZCAnREMnIGluIHRoZSBgc3RhdGVzX2xpc3RgIHRpYmJsZS4KCiMjIyMgQWZ0ZXIgc29tZSBxdWljayByZXNlYXJjaCBpdCBzZWVtcyB0aGF0IHRoZXJlIGFyZSBvbmx5IDUwIFN0YXRlcyBpbiB0aGUgVVMuIFdhc2hpbmd0b24gREMgaXMgdGVjaGluY2FsbHkgbm90IGNvdW50ZWQgYXMgYSBzdGF0ZSBidXQgYXMgYSBGZWRlcmFsIERpc3RyaWN0LCBhcyBpdCBpcyB0aGUgc2VhdCBvZiBnb3Zlcm5tZW50LCBzbyB0aGF0IHdhcyB3aHkgaXQgd2Fzbid0IGluY2x1ZGVkIGluIHRoZSBgU3RhdGVzYCB0aWJibGUgb3JpZ2luYWxseS4gIFBSIGlzIFB1ZXJ0byBSaWNvIGFuZCBpcyBhbHNvIG5vdCBhIHN0YXRlIGJ1dCB0aGUgbGFyZ2VzdCBVUyB0ZXJyaXRvcnkuCgoKIyMjIyBJIHNoYWxsIGFkZCBEQyBhbmQgUFIgaW50byB0aGUgc3RhdGVfbGlzdCBhbmQgcmUtam9pbiBpdC4KCmBgYHtyfQojIEFkZGluZyAyIG5ldyBzdGF0ZXMKCnN0YXRlLmFiYiA8LSBhcHBlbmQoc3RhdGUuYWJiLCBjKCJEQyIsICJQUiIpKQpzdGF0ZS5uYW1lIDwtIGFwcGVuZChzdGF0ZS5uYW1lLCBjKCJEaXN0cmljdCBvZiBDb2x1bWJpYSIsICJQdWVydG8gUmljbyIpKQoKc3RhdGVfbGlzdCA8LSB0aWJibGUoc3RhdGUgPSBzdGF0ZS5hYmIsIHJlZ2lvbiA9IHRvbG93ZXIoc3RhdGUubmFtZSkpCmBgYAoKCmBgYHtyfQojIFJlLWpvaW5nIHRpYmJsZXMKCmZpcmVzX3N0YXRlcyA8LSBmaXJlc19zbWFsbCAlPiUKICBsZWZ0X2pvaW4oc3RhdGVfbGlzdCwgYnkgPSAic3RhdGUiKQpgYGAKCgpgYGB7cn0KIyBDaGVja2luZyB0aGUgam9pbiBoYXMgd29ya2VkIHByb3Blcmx5IGFuZCB0aGVyZSBhcmUgbm8gTkFzCgpmaXJlc19zdGF0ZXMgJT4lCiAgZmlsdGVyKGlzLm5hKHJlZ2lvbikpCmBgYAoKYGBge3J9CiMgQ29kZSBiZWxvdyBicmluZ3MgdXAgYSAidmVjdG9yIG1lbW9yeSBleGhhdXN0ZWQgKGxpbWl0IHJlYWNoZWQ/KSIgZXJyb3IKCiMgZmlyZXNfam9pbmVkIDwtIGZpcmVzX3N0YXRlcyAlPiUKIyAgcmlnaHRfam9pbihzdGF0ZV9tYXAsIGJ5ID0gInJlZ2lvbiIpCmBgYAoKCiMjIyMgVGhlIGRhdGEgc2V0IGFuZCBnZW8gaW5mb3JtYXRpb24gaXMgdG9vIGJpZyB0byBqb2luIHNvIEknbSBnb2luZyB0byBkbyBhIHN1bW1hcmlzZSBmaXJzdCB0byBnZXQgdGhlIG51bWJlciBvZiBmaXJlcyBwZXIgcmVnaW9uIGZpcnN0LgoKYGBge3J9CmZpcmVzX2pvaW5lZCA8LSBmaXJlc19zdGF0ZXMgJT4lIAogICAgc2VsZWN0KHJlZ2lvbikgJT4lCiAgICBncm91cF9ieShyZWdpb24pICU+JQogICAgc3VtbWFyaXNlKG51bV9maXJlcyA9IG4oKSkgJT4lCiAgICByaWdodF9qb2luKHN0YXRlX21hcCwgYnkgPSAicmVnaW9uIikKYGBgCgoqKlJlc3VsdCEhICBOb3cgZG9pbmcgZmlyc3QgZ2VvIHNwYXRpYWwgdmlzdWFsaXNhdGlvbioqCgoKIyMjIFRvdGFsIFdpbGRmaXJlcyBwZXIgc3RhdGUgZnJvbSAxOTkyLTIwMTUKCmBgYHtyfQpmaXJlc19qb2luZWQgJT4lIAogICAgZ2dwbG90ICsKICAgIChhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXAsIGZpbGwgPSBudW1fZmlyZXMpKSArIAogICAgZ2VvbV9wb2x5Z29uKCkgKyAKICAgIGdlb21fcGF0aChjb2xvciA9ICJ3aGl0ZSIpICsgCiAgICBzY2FsZV9maWxsX2Rpc3RpbGxlcihuYW1lID0gIk51bWJlciBvZiBGaXJlcyIsIHBhbGV0dGUgPSAiUHVCdUduIikgKyAKICAgIHRoZW1lX21hcCgpICsgCiAgICBjb29yZF9tYXAoIm1vbGx3ZWlkZSIpICsgIAogICAgZ2d0aXRsZSgiVG90YWwgVVMgV2lsZGZpcmVzIGZyb20gMTk5Mi0yMDE1IikgKyAKICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQpgYGAKCiMgMy4gR2VvIFNwYXRpYWwgVmlzdWFsaXNhdGlvbnMKCiMjIyBUaGUgZGF0YXNldCBoYXMgYSBjYXVzZSBvZiBmaXJlIGNvbHVtbiBzbyBJIHNoYWxsIG5vdyBjcmVhdGUgc29tZSBjYXVzYXRpb24gcGxvdHMuCgoKIyMjIyBHZXR0aW5nIGxpc3Qgb2YgZmlyZSBjYXVzZXMKCmBgYHtyfQpmaXJlc19zdGF0ZXMgJT4lCiAgZGlzdGluY3Qoc3RhdF9jYXVzZV9kZXNjcikgJT4lCiAgYXJyYW5nZSgtZGVzYyhzdGF0X2NhdXNlX2Rlc2NyKSkKYGBgCgoKIyMjIFRvdGFsIGZpcmUgYnkgY2F1c2UgaW4gdGFidWxhciBmb3JtCgpgYGB7cn0KZmlyZXNfc3RhdGVzICU+JQogIHNlbGVjdChzdGF0X2NhdXNlX2Rlc2NyKSAlPiUKICBncm91cF9ieShzdGF0X2NhdXNlX2Rlc2NyKSAlPiUKICBzdW1tYXJpc2UobnVtX2ZpcmVzID0gbiAoKSkgJT4lCiAgYXJyYW5nZShkZXNjKG51bV9maXJlcykpCiAgCmBgYAoKIyMjIE51bWJlciBvZiBmaXJlcyBieSBzdGF0ZSBpbiB0YWJ1bGFyIGZvcm0KCmBgYHtyfQpmaXJlc19zdGF0ZXMgJT4lCiAgc2VsZWN0KHJlZ2lvbikgJT4lCiAgZ3JvdXBfYnkocmVnaW9uKSAlPiUKICBzdW1tYXJpc2UobnVtX2ZpcmVzID0gbigpKSAlPiUKICBhcnJhbmdlKGRlc2MobnVtX2ZpcmVzKSkKYGBgCgoKIyMjIyBBcyB0aGUgY2F1c2UgbmVlZHMgdG8gYmUgZmlsdGVyZWQgYmVmb3JlIHRoZSBtYXAgam9pbiwgSSdtIGdvaW5nIHRvIGVpdGhlciBnb2luZyB0byBoYXZlIHRvIHJlcGVhdCBhIHdob2xlIGxvYWQgb2YgdGhlIHNhbWUgY29kZSBpbiBldmVyeSBzaW5nbGUgcGxvdCBvciB3cml0ZSBhIGZ1bmN0aW9uIHRoYXQgd2lsbCBkbyBpdCBmb3IgbWUgd2l0aCwgc2F2aW5nIGEgbG90IG9mIHR5cGluZyEKCmBgYHtyfQojIEZ1bmN0aW9uIGZvciBwbG90dGluZyBjYXVzZSBvZiBmaXJlCgpjYXVzZSA8LSBmdW5jdGlvbihjYXVzZSkgewogIGZpcmVzX3N0YXRlcyAlPiUKICAgIGZpbHRlcihzdGF0X2NhdXNlX2Rlc2NyID09IGNhdXNlKSAlPiUKICAgIGRwbHlyOjpzZWxlY3QocmVnaW9uKSAlPiUKICAgIGdyb3VwX2J5KHJlZ2lvbikgJT4lCiAgICBzdW1tYXJpc2UobnVtX2ZpcmVzID0gbiAoKSkgJT4lCiAgICByaWdodF9qb2luKHN0YXRlX21hcCwgYnkgPSAicmVnaW9uIikgJT4lCiAgICBnZ3Bsb3QgKwogICAgKGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCwgZmlsbCA9IG51bV9maXJlcykpICsgCiAgICBnZW9tX3BvbHlnb24oKSArIAogICAgZ2VvbV9wYXRoKGNvbG9yID0gIndoaXRlIikgKyAKICAgIHNjYWxlX2ZpbGxfZGlzdGlsbGVyKG5hbWUgPSAiTnVtYmVyIG9mIGZpcmVzIiwgcGFsZXR0ZSA9ICJQdUJ1R24iKSArIAogICAgdGhlbWVfbWFwKCkgKyAKICAgIGNvb3JkX21hcCgibW9sbHdlaWRlIikgKyAKICAgIGdndGl0bGUocGFzdGUwKCJUb3RhbCBVUyBXaWxkZmlyZXMgY2F1c2VkIGJ5ICIsIGNhdXNlLCAiIGZyb20gMTk5Mi0yMDE1IikpICsgCiAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKfQpgYGAKCgoKIyMjIFdpbGRmaXJlcyBjYXVzZWQgYnkgQXJzb24KCmBgYHtyfQpjYXVzZSgiQXJzb24iKQpgYGAKCioqQXJzb24gZG9lcyBzZWVtIG1vcmUgcHJldmFsZW50IGluIHRoZSBTRSBzdGF0ZXMgb2YgTWlzc2lzc2lwcGksIEdlb3JnaWEsIEFsYWJhbWEgYW5kIGFsc28gdGhlIHdlc3Rlcm4gc3RhdGUgb2YgQ2FsaWZvcm5pYS4qKgoKCiMjIyBXaWxkZmlyZXMgY2F1c2VkIGJ5IENhbXBmaXJlCgpgYGB7cn0KY2F1c2UoIkNhbXBmaXJlIikKYGBgCgoqKkNhbXBmaXJlcyBhcmUgdGhlIG1vc3QgcHJldmFsZW50IGluIHRoZSBXZXN0ZXJuIHN0YXRlcyBvZiBPcmVnb24sIENhbGlmb3JuaWEgYW5kIEFyaXpvbmEuKioKCgojIyMgV2lsZGZpcmVzIGNhdXNlZCBieSBDaGlsZHJlbgoKYGBge3J9CmNhdXNlKCJDaGlsZHJlbiIpCmBgYAoKKipGaXJlcyBieSBjaGlsZHJlbiBhcmUgc3ByZWFkIGFib3V0IHRoZSBjb3VudHJ5LCBidXQgdGhlIG1vc3QgcHJldmFsZW50IHN0YXRlcyBhcmUgQ2FsaWZvcm5pYSBpbiB0aGUgV2VzdCwgQWxhYmFtYSBhbmQgU291dGggQ2Fyb2xpbmEgYW5kIE5ldyBKZXJzZXkgaW4gdGhlIGVhc3QuKioKCgojIyMgV2lsZGZpcmVzIGNhdXNlZCBieSBEZWJyaXMgQnVybmluZwoKYGBge3J9CmNhdXNlKCJEZWJyaXMgQnVybmluZyIpCmBgYAoKKipGaXJlcyBieSBidXJuaW5nIGRlYnJpcyBhcmUgbW9zdGx5IGluIHRoZSBzb3V0aGVybiB3YXJtZXIgc3RhdGVzIG9mIFRleGFzLCBHZW9yZ2lhIGFuZCBOb3J0aCBDYXJvbGluYS4qKgoKCiMjIyBXaWxkZmlyZXMgY2F1c2VkIGJ5IEVxdWltZW50IFVzZQoKYGBge3J9CmNhdXNlKCJFcXVpcG1lbnQgVXNlIikKYGBgCioqTW9zdCBvZiB0aGUgZmlyZXMgY2F1c2VkIGJ5IGVxdWlwbWVudCBzZWVtIHRvIGJlIGluIENhbGlmb3JuaWEqKgoKCiMjIyBXaWxkZmlyZXMgY2F1c2VkIGJ5IEZpcmV3b3JrcwoKYGBge3J9CmNhdXNlKCJGaXJld29ya3MiKQpgYGAKCioqTW9zdCBvZiB0aGUgZmlyZXMgY2F1c2VkIGJ5IGZpcmV3b3JrcyBzZWVtIHRvIGJlIGluIHRoZSBub3J0aCBvZiB0aGUgY291bnRyeS4gIFByaW1hcmlseSBTb3V0aCBEYWtvdGEsIE1vbnRhbmEgYW5kIFdhc2hpbmd0b24gc3RhdGUuKioKCgoKIyMjIFdpbGRmaXJlcyBjYXVzZWQgYnkgTGlnaHRuaW5nCgpgYGB7cn0KY2F1c2UoIkxpZ2h0bmluZyIpCmBgYAoKKipBcGFydCBmcm9tIGEgaG90c3BvdCBvZiBsaWdodG5pbmcgc3RyaWtlcyBpbiBGbG9yaWRhLCB0aGUgdmFzdCBtYWpvcml0eSBvZiBmaXJlcyBjYXVzZWQgYnkgbGlnaHRuaW5nIGFyZSBpbiB0aGUgV2VzdCBvZiB0aGUgY291bnRyeS4gIFdpdGggdGhlIDMgbW9zdCBhZmZlY3RlZCBzdGF0ZXMgYmVpbmcgQ2FsaWZvcm5pYSwgT3JlZ29uIGFuZCBBcml6b25hLioqCgoKIyMjIFdpbGRmaXJlcyBjYXVzZWQgYnkgTWlzY2VsbGlvdXMKCmBgYHtyfQpjYXVzZSgiTWlzY2VsbGFuZW91cyIpCmBgYAoKKipUaGVyZSBzZWVtcyB0byBiZSBxdWl0ZSBhIGZldyBtaXNjZWxsYW5lb3VzIGNsYXNzaWZpY2F0aW9ucyBpbiBDYWxpZm9ybmlhLCBUZXhhcyBhbmQgTmV3IFlvcmsuKioKCgojIyMgV2lsZGZpcmVzIGNhdXNlZCBieSBNaXNzaW5nL1VuZGVmaW5lZAoKYGBge3J9CmNhdXNlKCJNaXNzaW5nL1VuZGVmaW5lZCIpCmBgYAoKKipUaGUgc3RhdGVzIHdpdGggdGhlIG1vc3QgbWlzc2luZyBvciB1bmRlZmluZWQgZGF0YSBpcyBOb3J0aCBhbmQgU291dGggQ2Fyb2xpbmEsIE9rbGFob21hIGFuZCBDYWxpZm9ybmlhLioqCgoKIyMjIFdpbGRmaXJlcyBjYXVzZWQgYnkgUG93ZXJsaW5lCgpgYGB7cn0KY2F1c2UoIlBvd2VybGluZSIpCmBgYAoKKipUZXhhcyBoYXMgdGhlIGxhcmdlc3QgYW1vdW50IG9mIHdpbGRmaXJlcyBjYXVzZWQgYnkgcG93ZXJsaW5lcy4gIFRoaXMgaXMgcG9zc2libHkgZHVlIHRvIHRoZSB3YXJtIGNsaW1hdGUgYW5kIHRoZSBsYXJnZSBwcm9wb3J0aW9uIG9mIHRoZSBzdGF0ZSB0aGF0IGlzIGRyeSBncmFzc2xhbmRzIHVzZWQgZm9yIGFncmljdWx0dXJlLiAoMSkgKioKCigxKSBodHRwczovL3VrLnJldXRlcnMuY29tL2FydGljbGUvdXMtd2lsZGZpcmVzLXRleGFzL3RyZWVzLWFuZC1wb3dlci1saW5lcy1jYXVzZWQtbWFqb3ItdGV4YXMtZmlyZS1pZFVTVFJFNzhKNzZBMjAxMTA5MjAKCgojIyMgV2lsZGZpcmVzIGNhdXNlZCBieSBSYWlscm9hZAoKYGBge3J9CmNhdXNlKCJSYWlscm9hZCIpCmBgYAoKKipCeSBmYXIgRmxvcmlkYSBoYXMgdGhlIG1vc3Qgd2lsZGZpcmVzIGNhdXNlZCBieSByYWlscm9hZHMuICBJIGZpbmQgdGhpcyByYXRoZXIgc3RyYW5nZSBhbmQgd2lsbCBkbyBzb21lIGZ1cnRoZXIgaW52ZXN0aWdhdGlvbi4qKgoKCiMjIyBXaWxkZmlyZXMgY2F1c2VkIGJ5IFNtb2tpbmcKCmBgYHtyfQpjYXVzZSgiU21va2luZyIpCmBgYAoKKipGaXJlcyBjYXVzZWQgYnkgc21va2luZyBzZWVtIHRvIGJlIHNwcmVhZCBhcm91bmQgdGhlIGNvdW50cnksIGJ1dCBtYWlubHkgb24gdGhlIGVhc3QgYW5kIHdlc3QgY29hc3RzLioqCgoKIyMjIFdpbGRmaXJlcyBjYXVzZWQgYnkgU3RydWN0dXJlCgpgYGB7cn0KY2F1c2UoIlN0cnVjdHVyZSIpCmBgYAoKKipTb3V0aCBEYWtvdGEgaGFzIHRoZSBsYXJnZXN0IHByb3BvcnRpb24gb2YgZmlyZXMgY2F1c2VkIGJ5IHN0cnVjdHVyZXMuKioKCgoKIyMjIyBVbnN1cnByaXNpbmdseSB0aGUgc291dGhlcm4gc3RhdGVzIHNlZW0gdG8gaGF2ZSBtb3JlIG9jY3VyZW5jZXMgb2Ygd2lsZGlmcmUgaW4gZ2VuZXJhbCwgbm8gZG91YnQgZHVlIHRvIHRoZSB3YXJtZXIgY2xpbWF0ZSBhdCB0aGVpciBsYXRpdHVkZXMgbGVhZGluZyB0byBkcnllciBncm91bmQgY292ZXIgd2hpY2ggY2FiIGFjdCBhcyBmdWVsLiAgQWxzbyB0aGUgMXN0IGFuZCAzcmQgc3RhdGVzIHdpdGggdGhlIGhpZ2hlc3QgbnVtYmVyIG9mIGZpcmVzIGFyZSBhbHNvIHRoZSAyIGxhcmdlc3QgU3RhdGVzIGJ5IHNpemUuIEhvd2V2ZXIgdGhlIDJuZCBoaWdoZXN0IFN0YXRlIGlzIEdlb3JnaWEsIHdoaWNoIGFsdGhvdWdoIGl0IGlzIGluIHRoZSBTb3V0aCBvZiB0aGUgY291bnRyeSBpcyBvbmx5IGFuIGF2ZXJhZ2Ugc2l6ZWQgU3RhdGUuICBUaGVyZWZvcmUgdG8gZ2V0IGEgYmV0dGVyIHBpY3R1cmUgb2Ygd2hhdCBpcyBnb2luZyBvbiBJJ20gZ29pbmcgdG8gbG9vayBhdCB0aGUgcHJvcG9ydGlvbiBvZiBmaXJlcyBvY2N1cmluZyBieSBzcXVhcmUgbWlsZSBieSBub3JtYWxpc2luZyB0aGUgU3RhdGUgc2l6ZS4KCiMjIyMgVGhlIGBkYXRhc2V0YCBwYWNrYWdlIGFsc28gaGFzIHRoZSBhcmVhIGluIHNxdWFyZSBtaWxlcyBvZiBlYWNoIHN0YXRlIGluY2x1ZGVkIGluIHRoZSBgc3RhdGUuYXJlYWAgdmVjdG9yLgoKYGBge3J9CnN0YXRlLmFyZWEKYGBgCgpgYGB7cn0KbGVuZ3RoKHN0YXRlLmFyZWEpCmBgYAoKIyMjIyBBbm5veWluZ2x5IGl0IGFsc28gb25seSBoYXMgNTAgc3RhdGVzIG5vdCA1MiBzbyBJIHdpbGwgbmVlZCB0byBhZGQgaW4gREMgYW5kIFBSIGJhY2sgaW4uICAKCihBcmVhIGZpZ3VyZXMgb2J0YWluZWQgZnJvbSBXaWtpcGVkaWEpCgpEQyA9IDY4IG1pbGVzXjIKUFIgPSAzNTE1IG1pbGVzXjIKCgpgYGB7cn0KIyBUbyBtYWtlIG15IGxpZmUgZWFzaWVyIEknbSBnb2luZyB0byByZW1vdmUgdGhlIHN0YXRlLmFiYiBhbmQgLm5hbWUgZmlsZXMgYW5kIG1ha2UgdGhlIHRpYmJsZSBhZ2FpbiwgYWRkaW5nIGluIHRoZSBsYW5kIGFyZWEgZmlndXJlcyBhdCB0aGUgc2FtZSB0aW1lIHRvIG1ha2Ugc3VyZSB0aGV5IGFyZSBpbiB0aGUgY29ycmVjdCBvcmRlci4KCnJtKHN0YXRlLmFiYikKcm0oc3RhdGUubmFtZSkKCnN0YXRlLmFiYiA8LSBhcHBlbmQoc3RhdGUuYWJiLCBjKCJEQyIsICJQUiIpKQpzdGF0ZS5uYW1lIDwtIGFwcGVuZChzdGF0ZS5uYW1lLCBjKCJEaXN0cmljdCBvZiBDb2x1bWJpYSIsICJQdWVydG8gUmljbyIpKQpzdGF0ZS5hcmVhIDwtIGFwcGVuZChzdGF0ZS5hcmVhLCBjKCI2OCIsICIzNTE1IikpCgpzdGF0ZV9saXN0IDwtIHRpYmJsZShzdGF0ZSA9IHN0YXRlLmFiYiwgcmVnaW9uID0gdG9sb3dlcihzdGF0ZS5uYW1lKSwgYXJlYSA9IGFzLm51bWVyaWMoc3RhdGUuYXJlYSkpCmBgYAoKYGBge3J9CiMgUmUtam9pbmluZyB0aWJibGVzCgpmaXJlc19zdGF0ZXMgPC0gZmlyZXNfc21hbGwgJT4lCiAgbGVmdF9qb2luKHN0YXRlX2xpc3QsIGJ5ID0gInN0YXRlIikKYGBgCgoKIyMjIE5vcm1hbGlzaW5nIFN0YXRlcyBhcmVhIHNpemVzCgpgYGB7cn0KZmlyZXNfc3RhdGVzICU+JQogIHNlbGVjdChyZWdpb24sIGFyZWEpICU+JQogIGdyb3VwX2J5KHJlZ2lvbikgJT4lCiAgc3VtbWFyaXNlKG51bV9maXJlcyA9IG4oKSkgJT4lCiAgYXJyYW5nZShkZXNjKG51bV9maXJlcykpCmBgYAoKCgpgYGB7cn0KZmlyZXNfc3RhdGVzICU+JQogIHNlbGVjdChyZWdpb24sIGFyZWEpICU+JQogIGdyb3VwX2J5KHJlZ2lvbiwgYXJlYSkgJT4lCiAgc3VtbWFyaXNlKG51bV9maXJlcyA9IG4oKSkgJT4lCiAgbXV0YXRlKGZpcmVzX3NxbWlsZSA9IG51bV9maXJlcyAvIGFyZWEpICU+JQogIGFycmFuZ2UoZGVzYyhmaXJlc19zcW1pbGUpKQpgYGAKCiMjIyMgVGhpcyB0YWJsZSBzaG93cyBQdWVydG8gUmljbyBoYXMgdGhlIGhpZ2hlc3QgcHJvcG9ydGlvbiBvZiBmaXJlcyBjb21wYXJlZCB0byBpdHMgc2l6ZSwgZm9sbG93ZWQgYnkgTmV3IEplcnNleSBpbiB0aGUgTkUgb2YgdGhlIGNvdW50cnkgYW5kIGZpbmFsbHkgYnkgdGhlIFN0YXRlcyBpbiB0aGUgU0Ugb2YgdGhlIGNvdW50cnkuCgoKYGBge3J9CmZpcmVzX3N0YXRlcyAlPiUKICBzZWxlY3QocmVnaW9uLCBhcmVhKSAlPiUKICBncm91cF9ieShyZWdpb24sIGFyZWEpICU+JQogIHN1bW1hcmlzZShudW1fZmlyZXMgPSBuKCkpICU+JQogIG11dGF0ZShmaXJlc19zcW1pbGUgPSBudW1fZmlyZXMgLyBhcmVhKSAlPiUKICByaWdodF9qb2luKHN0YXRlX21hcCwgYnkgPSAicmVnaW9uIikgJT4lCiAgZ2dwbG90ICsKICAoYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwLCBmaWxsID0gZmlyZXNfc3FtaWxlKSkgKyAKICBnZW9tX3BvbHlnb24oKSArIAogIGdlb21fcGF0aChjb2xvciA9ICJ3aGl0ZSIpICsgCiAgc2NhbGVfZmlsbF9kaXN0aWxsZXIobmFtZSA9ICJGaXJlIHBlciBTcSBNaWxlIiwgcGFsZXR0ZSA9ICJQdUJ1R24iKSArCiAgdGhlbWVfbWFwKCkgKyAKICBjb29yZF9tYXAoIm1vbGx3ZWlkZSIpICsgCiAgZ2d0aXRsZShwYXN0ZTAoIlRvdGFsIFVTIFdpbGRmaXJlcyBwZXIgU3F1YXJlIE1pbGUgZnJvbSAxOTkyLTIwMTUiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKYGBgCgoKKipQdWVydG8gUmljbyBpcyBub3Qgc2hvd24gb24gdGhpcyBtYXAsIGJ1dCB2aXN1YWxseSB3ZSBjYW4gc2VlIHRoZSBkYXRhIGZvciB0aGUgb3RoZXIgNTEgZW50cmllcywgYW5kIHRoZSBzb3V0aCBlYXN0ZXJuIHN0YXRlcyBzdGlsbCBoYXZlIHRoZSBoaWdoZXN0IHByb3BvcnRpb24gb2Ygd2lsZGZpcmVzLiAgSW50ZXJlc3RpbmdseSBOZXcgSmVyc2V5IGFsc28gc2hvd3MgaGFzIGEgaG90c3BvdCBpbiB0aGUgTkUgb2YgdGhlIGNvdW50cnkuKioKCgojIyMgRG8gY2F1c2VzIGNoYW5nZSBvdmVyIHRpbWU/CgoKIyMjIyBTcGxpdHRpbmcgY2F1c2VzIGludG8gMiBncm91cCBmb3IgbGVnaWJpbGl0eS4gCgojIyMjIFRoZSBmaXJzdCBncm91cCBpcyBmb3IgZGlyZWN0bHkgbWFuIGNyZWF0ZWQgZmlyZXMuCgpgYGB7cn0KZmlyZXNfc3RhdGVzICU+JQogIHNlbGVjdChzdGF0X2NhdXNlX2Rlc2NyLCBmaXJlX3llYXIpICU+JQogIGdyb3VwX2J5KGZpcmVfeWVhciwgc3RhdF9jYXVzZV9kZXNjcikgJT4lCiAgZmlsdGVyKHN0YXRfY2F1c2VfZGVzY3IgPT0gIkFyc29uIiB8IHN0YXRfY2F1c2VfZGVzY3IgPT0gIkNhbXBmaXJlIiB8CiAgICAgICAgICAgc3RhdF9jYXVzZV9kZXNjciA9PSAiQ2hpbGRyZW4iIHwgc3RhdF9jYXVzZV9kZXNjciA9PSAiRXF1aXBtZW50IFVzZSIgfAogICAgICAgICAgIHN0YXRfY2F1c2VfZGVzY3IgPT0gIkZpcmV3b3JrcyIgfCBzdGF0X2NhdXNlX2Rlc2NyID09ICJTbW9raW5nIikgJT4lCiAgc3VtbWFyaXNlKG51bV9maXJlcyA9IG4oKSkgJT4lCiAgZ2dwbG90ICsKICBhZXMoeCA9IGZpcmVfeWVhciwgeSA9IG51bV9maXJlcywgY29sb3VyID0gc3RhdF9jYXVzZV9kZXNjcikgKwogIGdlb21fbGluZSgpICsKICBnZ3RpdGxlKCJBbW91bnQgb2YgZmlyZXMgYnkgY2F1c2UsIGZvciB5ZWFycyAxOTkyLTIwMTVcbiIpICsgCiAgeGxhYigiXG5ZZWFyIikgKwogIHlsYWIoIk51bWJlciBvZiBGaXJlc1xuIikgKwogIGxhYnMoY29sb3VyID0gIkNhdXNlIG9mIGZpcmUiKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCmBgYAoKKipUaGUgMiBsYXJnZSBwZWFrcyBpbiBBcnNvbiBhcmUgb2J2aW91cyBpbiAxOTk5IGFuZCAyMDA2LiBUaGVyZSB3YXMgYSBsYXJnZSBoZWF0d2F2ZSBpbiAyMDA2LCBidXQgSSdtIG5vdCBzdXJlIHdoeSB0aGlzIHdvdWxkIHJlc3VsdCBpbiBhbiBpbmNyZWFzZSBpbiBhcnNvbi4gIFBlcmhhcHMgdGhlcmUgd2Fzbid0IGFuIGFjdHVhbCBpbmNyZWFzZSBpbiB0aGUgYW1vdW50IG9mIGFyc29uLCBidXQgaXQgY291bGQgaGF2ZSBiZWVuIGR1ZSB0byB0aGUgaGVhdHdhdmUgbWFraW5nIHRoZSBncm91bmQgZHJpZXIgdGhhbiBub3JtYWwgY3JlYXRpbmcgZXh0cmEgZnVlbCB0byBhaWQgdGhlIHNwcmVhZCBvZiBmaXJlcyB0aGF0IHdvdWxkIGhhdmUgbm9ybWFsbHkgbm90IHJlc3VsdGVkIGluIGEgbGFyZ2Ugc2NhbGUgZmlyZS4gIFRoaXMgbWF5IGFsc28gYmUgdGhlIHNhbWUgcmVhc29uIHRoYXQgdGhlcmUgaXMgYWxzbyBhbm90aGVyIHBlYWsgaW4gMjAwNiBmb3IgRXF1aXBtZW50IFVzZS4gIEFyc29uIGhvd2V2ZXIgZG9lcyBsb29rIHRvIGJlIGRlY3JlYXNpbmcgc2luY2UgMjAwNiwgYXMgZG9lcyBjaGlsZHJlbi4gIE90aGVyIHdpc2UgbW9zdCBvZiB0aGUgb3RoZXIgY2F1c2VzIG9mIHdpbGRmaXJlcyBzZWVtIHRvIGJlIHJlYXNvbmFibHkgc3RhYmxlLiAgUGVyaGFwcyB3ZSBzaGFsbCB0cnkgbW9kZWxsaW5nIGFyc29uIGFuZCBjaGlsZHJlbiByZWxhdGVkIGZpcmVzIHRvIHNlZSBpZiB3ZSBjYW4gaWRlbnRpZnkgYSBnZW5lcmFsIHRyZW5kLioqCgoKIyMjIyBBbmQgdGhpcyBvbmUgZm9yIG5hdHVyYWwgb2NjdXJpbmcgZmlyZXMuCgpgYGB7cn0KZmlyZXNfc3RhdGVzICU+JQogIHNlbGVjdChzdGF0X2NhdXNlX2Rlc2NyLCBmaXJlX3llYXIpICU+JQogIGdyb3VwX2J5KGZpcmVfeWVhciwgc3RhdF9jYXVzZV9kZXNjcikgJT4lCiAgZmlsdGVyKHN0YXRfY2F1c2VfZGVzY3IgPT0gIkRlYnJpcyBCdXJuaW5nIiB8IHN0YXRfY2F1c2VfZGVzY3IgPT0gIkxpZ2h0bmluZyIgfAogICAgICAgICAgIHN0YXRfY2F1c2VfZGVzY3IgPT0gIk1pc2NlbGxhbmVvdXMiIHwgc3RhdF9jYXVzZV9kZXNjciA9PSAKICAgICAgICAgICAiTWlzc2luZy9VbmRlZmluZWQiIHwgc3RhdF9jYXVzZV9kZXNjciA9PSAiUG93ZXJsaW5lIiB8IAogICAgICAgICAgIHN0YXRfY2F1c2VfZGVzY3IgPT0gIlJhaWxyb2FkIiB8IHN0YXRfY2F1c2VfZGVzY3IgPT0gIlN0cnVjdHVyZSIpICU+JQogIHN1bW1hcmlzZShudW1fZmlyZXMgPSBuKCkpICU+JQogIGdncGxvdCArCiAgYWVzKHggPSBmaXJlX3llYXIsIHkgPSBudW1fZmlyZXMsIGNvbG91ciA9IHN0YXRfY2F1c2VfZGVzY3IpICsKICBnZW9tX2xpbmUoKSArCiAgZ2d0aXRsZSgiQW1vdW50IG9mIGZpcmVzIGJ5IGNhdXNlLCBmb3IgeWVhcnMgMTk5Mi0yMDE1XG4iKSArIAogIHhsYWIoIlxuWWVhciIpICsKICB5bGFiKCJOdW1iZXIgb2YgRmlyZXNcbiIpICsKICBsYWJzKGNvbG91ciA9ICJDYXVzZSBvZiBmaXJlIikgKwogIHRoZW1lX2J3KCkgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQpgYGAKCioqU2ltaWxhciBwZWFrcyBjYW4gYmUgc2VlbiBpbiBEZWJyaXMsIE1pc2NlbGxhbmVvdXMgYW5kIGxpZ2h0bmluZyBpbiB0aGUgaGVhdHdhdmUgb2YgMjAwNiB0aGF0IGxlZnQgdGhlIGdyb3VuZCB2ZXJ5IGRyeS4gIFRoZXJlIGFyZSBwZWFrcyBmcm9tIDE5OTcgdG8gMjAwMyBpbiBkZWJyaXMsIG1pc2NlbGxhbmVvdXMgYW5kIGxpZ2h0ZW5pbmcsIGJ1dCBhbHNvIGEgdHJvdWdoIGluIG1pc3NpbmcvdW5kZWZpbmVkLCBzbyB0aGlzIGlzIGxpa2VseSB0byBiZSBkdWUgdG8gbW9yZSBhY2N1cmF0ZSBjbGFzc2lmaWNhdGlvbiBvZiBmaXJlcyBhbmQgbm90IHVzaW5nIHRoZSBtaXNzaW5nL3VuZGVmaW5lZCBjYXRlZ29yeSBhcyBtdWNoLioqCgoKCiMjIyBEaWZmZXJlbmNlIGluIGNhdXNlcyBiZXR3ZWVuIHN0YXRlcwoKCmBgYHtyfQpzdGF0ZV9tYXBfc291dGhlcm4gPC0gc3RhdGVfbWFwICU+JQogIGZpbHRlcihyZWdpb24gPT0gImZsb3JpZGEiIHwgcmVnaW9uID09ICJnZW9yZ2lhIiB8IHJlZ2lvbiA9PSAiYWxhYmFtYSIgfAogICAgICAgICAgIHJlZ2lvbiA9PSAibWlzc2lzc2lwcGkiIHwgcmVnaW9uID09ICJzb3V0aCBjYXJvbGluYSIgfCAKICAgICAgICAgICByZWdpb24gPT0gIm5vcnRoIGNhcm9saW5hIiB8IHJlZ2lvbiA9PSAidGVubmVzc2VlIiB8IAogICAgICAgICAgIHJlZ2lvbiA9PSAiYXJrYW5zYXMiIHwgcmVnaW9uID09ICJsb3Vpc2lhbmEiKQpgYGAKCgpgYGB7cn0KZmlyZXNfc3RhdGVzICU+JQogIGZpbHRlcihmaXJlX3llYXIgPT0gIjE5OTIiIHwgZmlyZV95ZWFyID09ICIxOTkzIiB8IGZpcmVfeWVhciA9PSAiMTk5NCIgfAogICAgICAgICAgIGZpcmVfeWVhciA9PSAiMTk5NSIpICU+JQogIGZpbHRlcihyZWdpb24gPT0gImZsb3JpZGEiIHwgcmVnaW9uID09ICJnZW9yZ2lhIiB8IHJlZ2lvbiA9PSAiYWxhYmFtYSIgfAogICAgICAgICAgIHJlZ2lvbiA9PSAibWlzc2lzc2lwcGkiIHwgcmVnaW9uID09ICJzb3V0aCBjYXJvbGluYSIgfCAKICAgICAgICAgICByZWdpb24gPT0gIm5vcnRoIGNhcm9saW5hIiB8IHJlZ2lvbiA9PSAidGVubmVzc2VlIiB8CiAgICAgICAgICAgcmVnaW9uID09ICJhcmthbnNhcyIgfCByZWdpb24gPT0gImxvdWlzaWFuYSIpICU+JQogIHNlbGVjdChyZWdpb24sIHN0YXRfY2F1c2VfZGVzY3IpICU+JQogIGdyb3VwX2J5KHJlZ2lvbiwgc3RhdF9jYXVzZV9kZXNjcikgJT4lCiAgc3VtbWFyaXNlKG51bV9maXJlID0gbigpKSAlPiUKICB0b3BfbigxKSAlPiUKICByaWdodF9qb2luKHN0YXRlX21hcF9zb3V0aGVybiwgYnkgPSAicmVnaW9uIikgJT4lCiAgZ2dwbG90ICsKICAoYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwLCBmaWxsID0gc3RhdF9jYXVzZV9kZXNjcikpICsgCiAgZ2VvbV9wb2x5Z29uKCkgKyAKICBnZW9tX3BhdGgoY29sb3IgPSAid2hpdGUiKSArIAogIHRoZW1lX21hcCgpICsgCiAgc2NhbGVfZmlsbF9icmV3ZXIobmFtZSA9ICJDYXVzZSBvZiBGaXJlcyIsIHBhbGV0dGUgPSAiUHVCdUduIikgKwogIGdndGl0bGUoIlRvdGFsIFVTIFdpbGRmaXJlcyBtYWluIGNhdXNlIGZyb20gMTk5Mi0xOTk1IikgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKYGBgCgoKYGBge3J9CmZpcmVzX3N0YXRlcyAlPiUKICBmaWx0ZXIoZmlyZV95ZWFyID09ICIxOTk2IiB8IGZpcmVfeWVhciA9PSAiMTk5NyIgfCBmaXJlX3llYXIgPT0gIjE5OTgiIHwKICAgICAgICAgICBmaXJlX3llYXIgPT0gIjE5OTkiKSAlPiUKICBmaWx0ZXIocmVnaW9uID09ICJmbG9yaWRhIiB8IHJlZ2lvbiA9PSAiZ2VvcmdpYSIgfCByZWdpb24gPT0gImFsYWJhbWEiIHwKICAgICAgICAgICByZWdpb24gPT0gIm1pc3Npc3NpcHBpIiB8IHJlZ2lvbiA9PSAic291dGggY2Fyb2xpbmEiIHwgCiAgICAgICAgICAgcmVnaW9uID09ICJub3J0aCBjYXJvbGluYSIgfCByZWdpb24gPT0gInRlbm5lc3NlZSIgfAogICAgICAgICAgIHJlZ2lvbiA9PSAiYXJrYW5zYXMiIHwgcmVnaW9uID09ICJsb3Vpc2lhbmEiKSAlPiUKICBzZWxlY3QocmVnaW9uLCBzdGF0X2NhdXNlX2Rlc2NyKSAlPiUKICBncm91cF9ieShyZWdpb24sIHN0YXRfY2F1c2VfZGVzY3IpICU+JQogIHN1bW1hcmlzZShudW1fZmlyZSA9IG4oKSkgJT4lCiAgdG9wX24oMSkgJT4lCiAgcmlnaHRfam9pbihzdGF0ZV9tYXBfc291dGhlcm4sIGJ5ID0gInJlZ2lvbiIpICU+JQogIGdncGxvdCArCiAgKGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCwgZmlsbCA9IHN0YXRfY2F1c2VfZGVzY3IpKSArIAogIGdlb21fcG9seWdvbigpICsgCiAgZ2VvbV9wYXRoKGNvbG9yID0gIndoaXRlIikgKyAKICB0aGVtZV9tYXAoKSArIAogIHNjYWxlX2ZpbGxfYnJld2VyKG5hbWUgPSAiQ2F1c2Ugb2YgRmlyZXMiLCBwYWxldHRlID0gIlB1QnVHbiIpICsKICBnZ3RpdGxlKCJUb3RhbCBVUyBXaWxkZmlyZXMgbWFpbiBjYXVzZSBmcm9tIDE5OTYtMTk5OSIpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCmBgYAoKCmBgYHtyfQpmaXJlc19zdGF0ZXMgJT4lCiAgZmlsdGVyKGZpcmVfeWVhciA9PSAiMjAwMCIgfCBmaXJlX3llYXIgPT0gIjIwMDEiIHwgZmlyZV95ZWFyID09ICIyMDAyIiB8CiAgICAgICAgICAgZmlyZV95ZWFyID09ICIyMDAzIikgJT4lCiAgZmlsdGVyKHJlZ2lvbiA9PSAiZmxvcmlkYSIgfCByZWdpb24gPT0gImdlb3JnaWEiIHwgcmVnaW9uID09ICJhbGFiYW1hIiB8CiAgICAgICAgICAgcmVnaW9uID09ICJtaXNzaXNzaXBwaSIgfCByZWdpb24gPT0gInNvdXRoIGNhcm9saW5hIiB8IAogICAgICAgICAgIHJlZ2lvbiA9PSAibm9ydGggY2Fyb2xpbmEiIHwgcmVnaW9uID09ICJ0ZW5uZXNzZWUiIHwKICAgICAgICAgICByZWdpb24gPT0gImFya2Fuc2FzIiB8IHJlZ2lvbiA9PSAibG91aXNpYW5hIikgJT4lCiAgc2VsZWN0KHJlZ2lvbiwgc3RhdF9jYXVzZV9kZXNjcikgJT4lCiAgZ3JvdXBfYnkocmVnaW9uLCBzdGF0X2NhdXNlX2Rlc2NyKSAlPiUKICBzdW1tYXJpc2UobnVtX2ZpcmUgPSBuKCkpICU+JQogIHRvcF9uKDEpICU+JQogIHJpZ2h0X2pvaW4oc3RhdGVfbWFwX3NvdXRoZXJuLCBieSA9ICJyZWdpb24iKSAlPiUKICBnZ3Bsb3QgKwogIChhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXAsIGZpbGwgPSBzdGF0X2NhdXNlX2Rlc2NyKSkgKyAKICBnZW9tX3BvbHlnb24oKSArIAogIGdlb21fcGF0aChjb2xvciA9ICJ3aGl0ZSIpICsgCiAgdGhlbWVfbWFwKCkgKyAKICBzY2FsZV9maWxsX2JyZXdlcihuYW1lID0gIkNhdXNlIG9mIEZpcmVzIiwgcGFsZXR0ZSA9ICJQdUJ1R24iKSArCiAgZ2d0aXRsZSgiVG90YWwgVVMgV2lsZGZpcmVzIG1haW4gY2F1c2UgZnJvbSAyMDAwLTIwMDMiKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQpgYGAKCgpgYGB7cn0KZmlyZXNfc3RhdGVzICU+JQogIGZpbHRlcihmaXJlX3llYXIgPT0gIjIwMDQiIHwgZmlyZV95ZWFyID09ICIyMDA1IiB8IGZpcmVfeWVhciA9PSAiMjAwNiIgfAogICAgICAgICAgIGZpcmVfeWVhciA9PSAiMjAwNyIpICU+JQogIGZpbHRlcihyZWdpb24gPT0gImZsb3JpZGEiIHwgcmVnaW9uID09ICJnZW9yZ2lhIiB8IHJlZ2lvbiA9PSAiYWxhYmFtYSIgfAogICAgICAgICAgIHJlZ2lvbiA9PSAibWlzc2lzc2lwcGkiIHwgcmVnaW9uID09ICJzb3V0aCBjYXJvbGluYSIgfCAKICAgICAgICAgICByZWdpb24gPT0gIm5vcnRoIGNhcm9saW5hIiB8IHJlZ2lvbiA9PSAidGVubmVzc2VlIiB8CiAgICAgICAgICAgcmVnaW9uID09ICJhcmthbnNhcyIgfCByZWdpb24gPT0gImxvdWlzaWFuYSIpICU+JQogIHNlbGVjdChyZWdpb24sIHN0YXRfY2F1c2VfZGVzY3IpICU+JQogIGdyb3VwX2J5KHJlZ2lvbiwgc3RhdF9jYXVzZV9kZXNjcikgJT4lCiAgc3VtbWFyaXNlKG51bV9maXJlID0gbigpKSAlPiUKICB0b3BfbigxKSAlPiUKICByaWdodF9qb2luKHN0YXRlX21hcF9zb3V0aGVybiwgYnkgPSAicmVnaW9uIikgJT4lCiAgZ2dwbG90ICsKICAoYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwLCBmaWxsID0gc3RhdF9jYXVzZV9kZXNjcikpICsgCiAgZ2VvbV9wb2x5Z29uKCkgKyAKICBnZW9tX3BhdGgoY29sb3IgPSAid2hpdGUiKSArIAogIHRoZW1lX21hcCgpICsgCiAgc2NhbGVfZmlsbF9icmV3ZXIobmFtZSA9ICJDYXVzZSBvZiBGaXJlcyIsIHBhbGV0dGUgPSAiUHVCdUduIikgKwogIGdndGl0bGUoIlRvdGFsIFVTIFdpbGRmaXJlcyBtYWluIGNhdXNlIGZyb20gMjAwNC0yMDA3IikgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKYGBgCgoKCmBgYHtyfQpmaXJlc19zdGF0ZXMgJT4lCiAgZmlsdGVyKGZpcmVfeWVhciA9PSAiMjAwOCIgfCBmaXJlX3llYXIgPT0gIjIwMDkiIHwgZmlyZV95ZWFyID09ICIyMDEwIiB8CiAgICAgICAgICAgZmlyZV95ZWFyID09ICIyMDExIikgJT4lCiAgZmlsdGVyKHJlZ2lvbiA9PSAiZmxvcmlkYSIgfCByZWdpb24gPT0gImdlb3JnaWEiIHwgcmVnaW9uID09ICJhbGFiYW1hIiB8CiAgICAgICAgICAgcmVnaW9uID09ICJtaXNzaXNzaXBwaSIgfCByZWdpb24gPT0gInNvdXRoIGNhcm9saW5hIiB8IAogICAgICAgICAgIHJlZ2lvbiA9PSAibm9ydGggY2Fyb2xpbmEiIHwgcmVnaW9uID09ICJ0ZW5uZXNzZWUiIHwKICAgICAgICAgICByZWdpb24gPT0gImFya2Fuc2FzIiB8IHJlZ2lvbiA9PSAibG91aXNpYW5hIikgJT4lCiAgc2VsZWN0KHJlZ2lvbiwgc3RhdF9jYXVzZV9kZXNjcikgJT4lCiAgZ3JvdXBfYnkocmVnaW9uLCBzdGF0X2NhdXNlX2Rlc2NyKSAlPiUKICBzdW1tYXJpc2UobnVtX2ZpcmUgPSBuKCkpICU+JQogIHRvcF9uKDEpICU+JQogIHJpZ2h0X2pvaW4oc3RhdGVfbWFwX3NvdXRoZXJuLCBieSA9ICJyZWdpb24iKSAlPiUKICBnZ3Bsb3QgKwogIChhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXAsIGZpbGwgPSBzdGF0X2NhdXNlX2Rlc2NyKSkgKyAKICBnZW9tX3BvbHlnb24oKSArIAogIGdlb21fcGF0aChjb2xvciA9ICJ3aGl0ZSIpICsgCiAgdGhlbWVfbWFwKCkgKyAKICBzY2FsZV9maWxsX2JyZXdlcihuYW1lID0gIkNhdXNlIG9mIEZpcmVzIiwgcGFsZXR0ZSA9ICJQdUJ1R24iKSArCiAgZ2d0aXRsZSgiVG90YWwgVVMgV2lsZGZpcmVzIG1haW4gY2F1c2UgZnJvbSAyMDA4LTIwMTEiKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQpgYGAKCgoKYGBge3J9CmZpcmVzX3N0YXRlcyAlPiUKICBmaWx0ZXIoZmlyZV95ZWFyID09ICIyMDEyIiB8IGZpcmVfeWVhciA9PSAiMjAxMyIgfCBmaXJlX3llYXIgPT0gIjIwMTQiIHwKICAgICAgICAgICBmaXJlX3llYXIgPT0gIjIwMTUiKSAlPiUKICBmaWx0ZXIocmVnaW9uID09ICJmbG9yaWRhIiB8IHJlZ2lvbiA9PSAiZ2VvcmdpYSIgfCByZWdpb24gPT0gImFsYWJhbWEiIHwKICAgICAgICAgICByZWdpb24gPT0gIm1pc3Npc3NpcHBpIiB8IHJlZ2lvbiA9PSAic291dGggY2Fyb2xpbmEiIHwgCiAgICAgICAgICAgcmVnaW9uID09ICJub3J0aCBjYXJvbGluYSIgfCByZWdpb24gPT0gInRlbm5lc3NlZSIgfAogICAgICAgICAgIHJlZ2lvbiA9PSAiYXJrYW5zYXMiIHwgcmVnaW9uID09ICJsb3Vpc2lhbmEiKSAlPiUKICBzZWxlY3QocmVnaW9uLCBzdGF0X2NhdXNlX2Rlc2NyKSAlPiUKICBncm91cF9ieShyZWdpb24sIHN0YXRfY2F1c2VfZGVzY3IpICU+JQogIHN1bW1hcmlzZShudW1fZmlyZSA9IG4oKSkgJT4lCiAgdG9wX24oMSkgJT4lCiAgcmlnaHRfam9pbihzdGF0ZV9tYXBfc291dGhlcm4sIGJ5ID0gInJlZ2lvbiIpICU+JQogIGdncGxvdCArCiAgKGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCwgZmlsbCA9IHN0YXRfY2F1c2VfZGVzY3IpKSArIAogIGdlb21fcG9seWdvbigpICsgCiAgZ2VvbV9wYXRoKGNvbG9yID0gIndoaXRlIikgKyAKICB0aGVtZV9tYXAoKSArIAogIHNjYWxlX2ZpbGxfYnJld2VyKG5hbWUgPSAiQ2F1c2Ugb2YgRmlyZXMiLCBwYWxldHRlID0gIlB1QnVHbiIpICsKICBnZ3RpdGxlKCJUb3RhbCBVUyBXaWxkZmlyZXMgbWFpbiBjYXVzZSBmcm9tIDIwMTItMjAxNSIpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCmBgYAoKKipMb29raW5nIGF0IHRoZXNlIHRyZW5kcyBzb21lIGludGVyZXN0aW5nIGluc2lnaHRzIGNhbiBiZSBzZWVuLiAgRm9yIHRoZSBjb21iaW5lZCB5ZWFycyBkYXRhIEZsb3JpZGEgc3RhbmRzIG91dCBhcyBoYXZpbmcgcmFpbHJvYWQgYXMgaXRzIG1haW4gY2F1c2Ugb2Ygd2lsZGZpcmUsIGJ1dCBmcm9tIHRoZSBhYm92ZSBwbG90cyBpdCBjYW4gYmUgc2VlbiB0aGF0IHRoZXNlIHJhaWxyb2FkIGZpcmVzIGFyZSBvbmx5IHRoZSBtYWluIGNhdXNlIHVwIHRvIHRoZSA0IHllYXJseSBwZXJpb2QgZW5kaW5nIGluIDIwMDMgYW5kIHRoZW4gdGhlIG1haW4gY2F1c2UgY2hhbmdlcyB0byBsaWdodG5pbmcgdW50aWwgdGhlIGVuZCBvZiB0aGUgY29sbGVjdGlvbiBwZXJpb2QgaW4gMjAxNS4gIFNpbWlsYXJseSBhcnNvbiBzZWVtIHJlYXNvbmFibHkgcG9wdWxhciBpbiB0aGUgc291dGhlcm4gc3RhdGVzIHVudGlsIDIwMDcsIHdoZW4gaXQgbm8gbG9uZ2VyIGFwcGVhcnMgYXMgdGhlIG1vc3QgY29tbW9uIGNhdXNlIG9mIHdpbGRmaXJlLiAgVGhpcyBkb3dud2FyZCB0cmVuZCB3YXMgYWxzbyBub3RlZCBlYXJsaWVyIGluIHRoZSBvdmVyYWxsIGNhdXNhdGlvbiBwbG90cyBmb3IgYWxsIHN0YXRlcyoqCgoKIyMjIFRoZSByYWlscm9hZCBmaXJlcyBpbiBGbG9yaWRhIGFyZSBxdWl0ZSBpbnRlcmVzdGluZyBjb25zaWRlcmluZyB0aGF0IG90aGVyIHNvdXRoZXJuIHN0YXRlcyBoYXZlIG1vcmUgd29vZGxhbmQgb3Igb3BlbiBwYXN0dXJlcyB0aGF0IEkgdGhvdWdodCB3b3VsZCBoYXZlIGJlZW4gbW9yZSBzdXNlcHRpYmxlIHRvIGZpcmUuICBJJ20gZ29pbmcgdG8gdHJ5IGFuZCBtb3JlIGNsb3NlbHkgbWFwIHJhaWxyb2FkIGZpcmVzIGluIEZsb3JpZGEgaXRzZWxmLgoKCmBgYHtyfQpmaXJlc19zdGF0ZXMgJT4lCiAgZHBseXI6OmZpbHRlcihyZWdpb24gPT0gImZsb3JpZGEiICYgc3RhdF9jYXVzZV9kZXNjciA9PSAiUmFpbHJvYWQiICYgCiAgICAgICAgICAgZmlyZV95ZWFyID09ICIxOTkyIikgJT4lCiAgbGVhZmxldCgpICU+JQogIGFkZFRpbGVzKCkgJT4lCiAgYWRkTWFya2VycyhsbmcgPSB+bG9uZ2l0dWRlLCBsYXQgPSB+bGF0aXR1ZGUsIGxhYmVsID0KICAgICAgICAgICAgICAgfnBhc3RlKCJGaXJlIFNpemU6ICIsIGZpcmVfc2l6ZSwgIi8gTW9udGg6ICIsIGRpc2NvdmVyeV9tb3kpKQoKYGBgCgoqKlRoZXJlIGlzIHNvbWV0aGluZyBub3QgcmlnaHQgd2l0aCB0aGlzIGRhdGEsIGl0IGlzIGV4dHJlbWVseSB1bmxpa2VseSB0aGF0IGFsbCB0aGVzZSBmaXJlIGFyZSBmcm9tIHJhaWxyb2FkcyAuIFNvIEknbSBnb2luZyB0byBjaGVjayBhbm90aGVyIHJhbmRvbSB5ZWFyIGluIDE5OTguKioKCgpgYGB7cn0KZmlyZXNfc3RhdGVzICU+JQogIGRwbHlyOjpmaWx0ZXIocmVnaW9uID09ICJmbG9yaWRhIiAmIHN0YXRfY2F1c2VfZGVzY3IgPT0gIlJhaWxyb2FkIiAmIAogICAgICAgICAgIGZpcmVfeWVhciA9PSAiMTk5OCIpICU+JQogIGxlYWZsZXQoKSAlPiUKICBhZGRUaWxlcygpICU+JQogIGFkZE1hcmtlcnMobG5nID0gfmxvbmdpdHVkZSwgbGF0ID0gfmxhdGl0dWRlLCBsYWJlbCA9CiAgICAgICAgICAgICAgIH5wYXN0ZSgiRmlyZSBTaXplOiAiLCBmaXJlX3NpemUsICIvIE1vbnRoOiAiLCBkaXNjb3ZlcnlfbW95KSkKCmBgYAoKKipUaGUgc2FtZSBpc3N1ZSBpcyBwcmVzZW50LCB0aGVyZSBpcyBkZWZpbml0ZWx5IHNvbWV0aGluZyB3cm9uZyBoZXJlLiAgTGV0J3MgY2hlY2sgc29tZSBtb3JlIHllYXJzLioqCgoKYGBge3J9CmZpcmVzX3N0YXRlcyAlPiUKICBkcGx5cjo6ZmlsdGVyKHJlZ2lvbiA9PSAiZmxvcmlkYSIgJiBzdGF0X2NhdXNlX2Rlc2NyID09ICJSYWlscm9hZCIgJiAKICAgICAgICAgICBmaXJlX3llYXIgPT0gIjIwMDgiKSAlPiUKICBsZWFmbGV0KCkgJT4lCiAgYWRkVGlsZXMoKSAlPiUKICBhZGRNYXJrZXJzKGxuZyA9IH5sb25naXR1ZGUsIGxhdCA9IH5sYXRpdHVkZSwgbGFiZWwgPQogICAgICAgICAgICAgICB+cGFzdGUoIkZpcmUgU2l6ZTogIiwgZmlyZV9zaXplLCAiLyBNb250aDogIiwgZGlzY292ZXJ5X21veSkpCgpgYGAKCioqTm93IHRoYXQgaXMgbXVjaCBiZXR0ZXIsIHdpdGggYSBsb3QgbGVzcyBmaXJlcyBvY2N1cnJpbmcgYW5kIGFsbCBvZiB0aGVtIG5leHQgdG8gYSByYWlscm9hZCBhcyB5b3Ugd291bGQgZXhwZWN0LiAgTGV0J3MgY2hlY2sgYW5vdGhlciB5ZWFyLioqCgoKYGBge3J9CmZpcmVzX3N0YXRlcyAlPiUKICBkcGx5cjo6ZmlsdGVyKHJlZ2lvbiA9PSAiZmxvcmlkYSIgJiBzdGF0X2NhdXNlX2Rlc2NyID09ICJSYWlscm9hZCIgJiAKICAgICAgICAgICBmaXJlX3llYXIgPT0gIjIwMTUiKSAlPiUKICBsZWFmbGV0KCkgJT4lCiAgYWRkVGlsZXMoKSAlPiUKICBhZGRNYXJrZXJzKGxuZyA9IH5sb25naXR1ZGUsIGxhdCA9IH5sYXRpdHVkZSwgbGFiZWwgPQogICAgICAgICAgICAgICB+cGFzdGUoIkZpcmUgU2l6ZTogIiwgZmlyZV9zaXplLCAiLyBNb250aDogIiwgZGlzY292ZXJ5X21veSkpCgpgYGAKCioqMjAxNSdzIGRhdGEgbG9va3MgdGhlIHNhbWUgYXMgMjAwOCBhbmQgd2hhdCBJIHdvdWxkIGV4cGVjdCBmb3IgcmFpbHJvYWQgZmlyZXMsIG9jY3VycmluZyBuZXh0IHRvIHJhaWxzIGFuZCBiZWluZyBmZXcgYW5kIGZhciBiZXR3ZWVuISoqCgoKKipIYXZpbmcgdXNlZCBsZWFmbGV0IHRvIHBsb3QgYWxsIHRoZSBMYXQvbG9uZyBjb29yZGluYXRlcyBmb3IgdGhlIHJhaWxyb2FkIGZpcmVzIGluIDE5OTIsIDE5OTgsIDIwMDggYW5kIDIwMTUsIEkgYW0gZG91YnRmdWwgb2YgdGhlIHZhbGlkaXR5IG9mIGVpdGhlciB0aGUgcmVjb3JkZWQgY2xhc3NpZmljYXRpb24gb2YgZmlyZSBvcmlnaW4gb3IgdGhlIGFjY3VyYWN5IG9mIHRoZSBjb29yZGluYXRlcyBpbiB0aGUgZWFybGllciB5ZWFycyBvZiB0aGUgcmVjb3JkaW5nIHBlcmlvZC4gIFRoZSBtYWpvcml0eSBvZiBwbG90dGVkIGZpcmVzIGhhdmUgYmVlbiBzdGFydGVkIG1hbnkgbWlsZXMgYXdheSBmcm9tIGFueSByYWlscm9hZC4gIFRoaXMgaXMgZXNwZWNpYWxseSBvYnZpb3VzIGZvciB0aGUgMiBmaXJlcyB0aGF0IG9jY3VycmVkIG5lYXIgS2V5IFdlc3QgaW4gMTk5Miwgd2hpY2ggaGFzIG5vIHJhaWwgbGlua3MgYW55d2hlcmUgbmVhciBieSBvbmx5IHJvYWQuICBUaGUgY29vcmRpbmF0ZXMgaGF2ZSBiZWVuIGdpdmVuIHRvIDUgZGVjaW1hbCBwbGFjZXMsIHdoaWNoIGFsbG93cyBhIHByZWNpc2lvbiBvZiAxLjEgbWV0ZXJzLCBzbyB1bmxlc3MgdGhleSBoYXZlIGJlZW4gZW50ZXJlZCBpbnRvIHRoZSBkYXRhYmFzZSBpbmNvcnJlY3RseSBJIHRoaW5rIGl0IGlzIHByb2JhYmx5IGZhciBtb3JlIGxpa2VseSB0aGF0IGFuIGluY29ycmVjdCBjYXVzZSBkZXNjcmlwdG9yIG1heSBoYXZlIGJlZW4gZW50ZXJlZCBmb3IgYSBsb3Qgb2YgZmlyZXMgaW4gdGhlIGVhcmxpZXIgeWVhcnMuICBUaGlzIGVycm9yIHNlZW1zIHRvIGhhdmUgYmVlbiByZWN0aWZpZWQgaW4gdGhlIGxhdGVyIHllYXJzIG9mIHRoZSBkYXRhc2V0LCBhcyBjYW4gYmUgc2VlbiBpbiB0aGUgMjAwOCBhbmQgMjAxNSBkYXRhIGJlaGF2aW5nIGFzIGV4cGVjdGVkIGFzIGFib3ZlLioqCgoKCgoKIyMjIENvcnJlbGF0aW9uIGJldHdlZW4gc3RhdGVzIGFuZCBmaXJlIHNpemUKCmBgYHtyfQpmaXJlc19zdGF0ZXMgJT4lCiAgc2VsZWN0KHJlZ2lvbiwgZmlyZV9zaXplX2NsYXNzKSAlPiUKICBncm91cF9ieShyZWdpb24sIGZpcmVfc2l6ZV9jbGFzcykgJT4lCiAgc3VtbWFyaXNlKG51bV9maXJlID0gbigpKSAlPiUKICB0b3BfbigxKSAlPiUKICByaWdodF9qb2luKHN0YXRlX21hcCwgYnkgPSAicmVnaW9uIikgJT4lCiAgZ2dwbG90ICsKICAoYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwLCBmaWxsID0gZmlyZV9zaXplX2NsYXNzKSkgKwogIGdlb21fcG9seWdvbigpICsKICBnZW9tX3BhdGgoY29sb3IgPSAid2hpdGUiKSArCiAgdGhlbWVfbWFwKCkgKwogIHNjYWxlX2ZpbGxfYnJld2VyKG5hbWUgPSAiRmlyZSBTaXplIENsYXNzIiwgcGFsZXR0ZSA9ICJQdUJ1R24iKSArCiAgZ2d0aXRsZSgiTW9zdCBjb21tb24gd2lsZGZpcmUgc2l6ZSBwZXIgU3RhdGUgMTk5Mi0yMDE1IikgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQpgYGAKCgpgYGB7cn0KZmlyZXNfc3RhdGVzICU+JQogIHNlbGVjdChyZWdpb24sIGZpcmVfc2l6ZV9jbGFzcykgJT4lCiAgZmlsdGVyKGZpcmVfc2l6ZV9jbGFzcyA9PSAiRyIpICU+JQogIGdyb3VwX2J5KHJlZ2lvbikgJT4lCiAgc3VtbWFyaXNlKG51bV9maXJlID0gbigpKSAlPiUKICByaWdodF9qb2luKHN0YXRlX21hcCwgYnkgPSAicmVnaW9uIikgJT4lCiAgZ2dwbG90ICsKICAoYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwLCBmaWxsID0gbnVtX2ZpcmUpKSArCiAgZ2VvbV9wb2x5Z29uKCkgKwogIGdlb21fcGF0aChjb2xvciA9ICJ3aGl0ZSIpICsKICB0aGVtZV9tYXAoKSArCiAgc2NhbGVfZmlsbF9kaXN0aWxsZXIobmFtZSA9ICJOdW1iZXIgb2YgRmlyZXMiLCBwYWxldHRlID0gIlB1QnVHbiIpICsKICBnZ3RpdGxlKCJOdW1iZXIgb2YgbGFyZ2UgY2xhc3MgRyBmaXJlcyBwZXIgU3RhdGUgMTk5Mi0yMDE1IikgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQpgYGAKCioqRnJvbSB0aGUgcGxvdHMgd2UgY2FuIHNlZSB0aGF0IHRoZSBXZXN0ZXJuIHN0YXRlcyBoYXZlIHRoZSBtb3N0IHNtYWxsIGZpcmVzIGFuZCBhbHNvIHRoZSBtb3N0IGxhcmdlIGZpcmVzISAgTm90IGVudGlyZWx5IHRoZSBtb3N0IGhlbHBmdWwgcGxvdHMuLi4qKgoKCgoKCiMjIyBBcmUgZmlyZXMgbW9yZSBwcmV2YWxlbnQgaW4gY2VydGFpbiBtb250aHMgZm9yIGluZGl2aWR1YWwgc3RhdGVzCgoKYGBge3J9CmZpcmVzX3N0YXRlcyAlPiUKICBkcGx5cjo6c2VsZWN0KHJlZ2lvbiwgZGlzY292ZXJ5X21veSkgJT4lCiAgZ3JvdXBfYnkocmVnaW9uLCBkaXNjb3ZlcnlfbW95KSAlPiUKICBzdW1tYXJpc2UobnVtX2ZpcmUgPSBuKCkpICU+JQogIHRvcF9uKDEpICU+JQogIHJpZ2h0X2pvaW4oc3RhdGVfbWFwLCBieSA9ICJyZWdpb24iKSAlPiUKICBnZ3Bsb3QgKwogIChhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXAsIGZpbGwgPSBkaXNjb3ZlcnlfbW95KSkgKwogIGdlb21fcG9seWdvbigpICsKICBnZW9tX3BhdGgoY29sb3IgPSAid2hpdGUiKSArCiAgdGhlbWVfbWFwKCkgKwogIHNjYWxlX2ZpbGxfYnJld2VyKG5hbWUgPSAiTW9udGhzIG9mIFllYXIiLCBwYWxldHRlID0gIlB1QnVHbiIpICsKICBnZ3RpdGxlKCJNb250aHMgd2l0aCBtb3N0IGZpcmVzIHBlciBTdGF0ZSAxOTkyLTIwMTUiKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCmBgYAoKCmBgYHtyfQpmaXJlc19zdGF0ZXMgJT4lCiAgZmlsdGVyKGZpcmVfeWVhciA9PSAiMTk5MiIgfCBmaXJlX3llYXIgPT0gIjE5OTMiIHwgZmlyZV95ZWFyID09ICIxOTk0IiB8CiAgICAgICAgICAgZmlyZV95ZWFyID09ICIxOTk1IikgJT4lCiAgc2VsZWN0KHJlZ2lvbiwgZGlzY292ZXJ5X21veSkgJT4lCiAgZ3JvdXBfYnkocmVnaW9uLCBkaXNjb3ZlcnlfbW95KSAlPiUKICBzdW1tYXJpc2UobnVtX2ZpcmUgPSBuKCkpICU+JQogIHRvcF9uKDEpICU+JQogIHJpZ2h0X2pvaW4oc3RhdGVfbWFwLCBieSA9ICJyZWdpb24iKSAlPiUKICBnZ3Bsb3QgKwogIChhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXAsIGZpbGwgPSBkaXNjb3ZlcnlfbW95KSkgKwogIGdlb21fcG9seWdvbigpICsKICBnZW9tX3BhdGgoY29sb3IgPSAid2hpdGUiKSArCiAgdGhlbWVfbWFwKCkgKwogIHNjYWxlX2ZpbGxfYnJld2VyKG5hbWUgPSAiTW9udGhzIG9mIFllYXIiLCBwYWxldHRlID0gIlB1QnVHbiIpICsKICBnZ3RpdGxlKCJNb250aCB3aXRoIG1vc3QgZmlyZXMgcGVyIFN0YXRlIDE5OTItMTk5NSIpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgCiAgIyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibGVmdCIpCmBgYAoKCgpgYGB7cn0KZmlyZXNfc3RhdGVzICU+JQogIGZpbHRlcihmaXJlX3llYXIgPT0gIjE5OTYiIHwgZmlyZV95ZWFyID09ICIxOTk3IiB8IGZpcmVfeWVhciA9PSAiMTk5OCIgfAogICAgICAgICAgIGZpcmVfeWVhciA9PSAiMTk5OSIpICU+JQogIHNlbGVjdChyZWdpb24sIGRpc2NvdmVyeV9tb3kpICU+JQogIGdyb3VwX2J5KHJlZ2lvbiwgZGlzY292ZXJ5X21veSkgJT4lCiAgc3VtbWFyaXNlKG51bV9maXJlID0gbigpKSAlPiUKICB0b3BfbigxKSAlPiUKICByaWdodF9qb2luKHN0YXRlX21hcCwgYnkgPSAicmVnaW9uIikgJT4lCiAgZ2dwbG90ICsKICAoYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwLCBmaWxsID0gZGlzY292ZXJ5X21veSkpICsKICBnZW9tX3BvbHlnb24oKSArCiAgZ2VvbV9wYXRoKGNvbG9yID0gIndoaXRlIikgKwogIHRoZW1lX21hcCgpICsKICBzY2FsZV9maWxsX2JyZXdlcihuYW1lID0gIk1vbnRocyBvZiBZZWFyIiwgcGFsZXR0ZSA9ICJQdUJ1R24iKSArCiAgZ2d0aXRsZSgiTW9udGggd2l0aCBtb3N0IGZpcmVzIHBlciBTdGF0ZSAxOTk2LTE5OTkiKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCmBgYAoKCgpgYGB7cn0KZmlyZXNfc3RhdGVzICU+JQogIGZpbHRlcihmaXJlX3llYXIgPT0gIjIwMDAiIHwgZmlyZV95ZWFyID09ICIyMDAxIiB8IGZpcmVfeWVhciA9PSAiMjAwMiIgfAogICAgICAgICAgIGZpcmVfeWVhciA9PSAiMjAwMyIpICU+JQogIHNlbGVjdChyZWdpb24sIGRpc2NvdmVyeV9tb3kpICU+JQogIGdyb3VwX2J5KHJlZ2lvbiwgZGlzY292ZXJ5X21veSkgJT4lCiAgc3VtbWFyaXNlKG51bV9maXJlID0gbigpKSAlPiUKICB0b3BfbigxKSAlPiUKICByaWdodF9qb2luKHN0YXRlX21hcCwgYnkgPSAicmVnaW9uIikgJT4lCiAgZ2dwbG90ICsKICAoYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwLCBmaWxsID0gZGlzY292ZXJ5X21veSkpICsKICBnZW9tX3BvbHlnb24oKSArCiAgZ2VvbV9wYXRoKGNvbG9yID0gIndoaXRlIikgKwogIHRoZW1lX21hcCgpICsKICBzY2FsZV9maWxsX2JyZXdlcihuYW1lID0gIk1vbnRocyBvZiBZZWFyIiwgcGFsZXR0ZSA9ICJQdUJ1R24iKSArCiAgZ2d0aXRsZSgiTW9udGggd2l0aCBtb3N0IGZpcmVzIHBlciBTdGF0ZSAyMDAwLTIwMDMiKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCmBgYAoKCgpgYGB7cn0KZmlyZXNfc3RhdGVzICU+JQogIGZpbHRlcihmaXJlX3llYXIgPT0gIjIwMDQiIHwgZmlyZV95ZWFyID09ICIyMDA1IiB8IGZpcmVfeWVhciA9PSAiMjAwNiIgfAogICAgICAgICAgIGZpcmVfeWVhciA9PSAiMjAwNyIpICU+JQogIHNlbGVjdChyZWdpb24sIGRpc2NvdmVyeV9tb3kpICU+JQogIGdyb3VwX2J5KHJlZ2lvbiwgZGlzY292ZXJ5X21veSkgJT4lCiAgc3VtbWFyaXNlKG51bV9maXJlID0gbigpKSAlPiUKICB0b3BfbigxKSAlPiUKICByaWdodF9qb2luKHN0YXRlX21hcCwgYnkgPSAicmVnaW9uIikgJT4lCiAgZ2dwbG90ICsKICAoYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwLCBmaWxsID0gZGlzY292ZXJ5X21veSkpICsKICBnZW9tX3BvbHlnb24oKSArCiAgZ2VvbV9wYXRoKGNvbG9yID0gIndoaXRlIikgKwogIHRoZW1lX21hcCgpICsKICBzY2FsZV9maWxsX2JyZXdlcihuYW1lID0gIk1vbnRocyBvZiBZZWFyIiwgcGFsZXR0ZSA9ICJQdUJ1R24iKSArCiAgZ2d0aXRsZSgiTW9udGggd2l0aCBtb3N0IGZpcmVzIHBlciBTdGF0ZSAyMDA0LTIwMDciKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCmBgYAoKCgpgYGB7cn0KZmlyZXNfc3RhdGVzICU+JQogIGZpbHRlcihmaXJlX3llYXIgPT0gIjIwMDgiIHwgZmlyZV95ZWFyID09ICIyMDA5IiB8IGZpcmVfeWVhciA9PSAiMjAxMCIgfAogICAgICAgICAgIGZpcmVfeWVhciA9PSAiMjAxMSIpICU+JQogIHNlbGVjdChyZWdpb24sIGRpc2NvdmVyeV9tb3kpICU+JQogIGdyb3VwX2J5KHJlZ2lvbiwgZGlzY292ZXJ5X21veSkgJT4lCiAgc3VtbWFyaXNlKG51bV9maXJlID0gbigpKSAlPiUKICB0b3BfbigxKSAlPiUKICByaWdodF9qb2luKHN0YXRlX21hcCwgYnkgPSAicmVnaW9uIikgJT4lCiAgZ2dwbG90ICsKICAoYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwLCBmaWxsID0gZGlzY292ZXJ5X21veSkpICsKICBnZW9tX3BvbHlnb24oKSArCiAgZ2VvbV9wYXRoKGNvbG9yID0gIndoaXRlIikgKwogIHRoZW1lX21hcCgpICsKICBzY2FsZV9maWxsX2JyZXdlcihuYW1lID0gIk1vbnRocyBvZiBZZWFyIiwgcGFsZXR0ZSA9ICJQdUJ1R24iKSArCiAgZ2d0aXRsZSgiTW9udGggd2l0aCBtb3N0IGZpcmVzIHBlciBTdGF0ZSAyMDA4LTIwMTEiKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCmBgYAoKCgpgYGB7cn0KZmlyZXNfc3RhdGVzICU+JQogIGZpbHRlcihmaXJlX3llYXIgPT0gIjIwMTIiIHwgZmlyZV95ZWFyID09ICIyMDEzIiB8IGZpcmVfeWVhciA9PSAiMjAxNCIgfAogICAgICAgICAgIGZpcmVfeWVhciA9PSAiMjAxNSIpICU+JQogIHNlbGVjdChyZWdpb24sIGRpc2NvdmVyeV9tb3kpICU+JQogIGdyb3VwX2J5KHJlZ2lvbiwgZGlzY292ZXJ5X21veSkgJT4lCiAgc3VtbWFyaXNlKG51bV9maXJlID0gbigpKSAlPiUKICB0b3BfbigxKSAlPiUKICByaWdodF9qb2luKHN0YXRlX21hcCwgYnkgPSAicmVnaW9uIikgJT4lCiAgZ2dwbG90ICsKICAoYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwLCBmaWxsID0gZGlzY292ZXJ5X21veSkpICsKICBnZW9tX3BvbHlnb24oKSArCiAgZ2VvbV9wYXRoKGNvbG9yID0gIndoaXRlIikgKwogIHRoZW1lX21hcCgpICsKICBzY2FsZV9maWxsX2JyZXdlcihuYW1lID0gIk1vbnRocyBvZiBZZWFyIiwgcGFsZXR0ZSA9ICJQdUJ1R24iKSArCiAgZ2d0aXRsZSgiTW9udGggd2l0aCBtb3N0IGZpcmVzIHBlciBTdGF0ZSAyMDEyLTIwMTUiKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCmBgYAoKCgoqKlRoZSBhYm92ZSBwbG90cyBhcmUgcXVpdGUgaW50ZXJlc3RpbmcuICBUaGUgbW9udGhzIG9mIHRoZSB5ZWFyIHRoYXQgaGF2ZSB0aGUgbW9zdCBzZWVtcyB0byB3aWRlbHkgY2hhbmdlIGluIGNlcnRhaW4gc3RhdGUuICBNYWlubHkgdGhlIGVhc3QgaGFsZiBvZiB0aGUgY291bnRyeSBoYXZlIHRoZSBtb3N0IGZpcmVzIGluIHRoZSBTcHJpbmcgKEZlYi1NYXkpIGFuZCB0aGUgd2VzdGVybiBwYXJ0IG9mIHRoZSBjb3VudHJ5IGhhdmUgdGhlIG1vc3QgZmlyZXMgbGF0ZXIgb24gaW4gU3VtbWVyIGFuZCBGYWxsIChKdW4tT2N0KS4gIFRoZXJlIGFyZSBob3dldmVyIGEgZmV3IGV4Y2VwdGlvbnMgdGhhdCBjYW4gYmUgc2VlbiBpbiB0aGUgMjAwNC0yMDA3IGFuZCAyMDA4LTIwMTEgZGF0YSBUZXhhcyBoYXMgdGhlIG1vc3QgZmlyZXMgaW4gSmFudWFyeS4gIEZsb3JpZGEgYWxzbyBtb3N0bHkgY29uZm9ybWVkIHRvIHRoZSBFYXN0L1dlc3Qgc3BsaXQgd2l0aCB0aGUgbWFqb3JpdHkgb2YgaXRzIHdvcnN0IG1vbnRocyBmb3IgZmlyZXMgdGFraW5nIHBsYWNlIGluIE1hcmNoIG9yIEFwcmlsIHVwIHVudGlsIDIwMDcsIHRoZW4gdGhlIG1vc3QgY29tbW9uIG1vbnRoIG1vdmVzIGxhdGVyIGludG8gSnVuZSBhbmQgSnVseSBmb3IgdGhlIHJlc3Qgb2YgdGhlIHJlcG9ydGluZyBwZXJpb2QgdW50aWwgMjAxNS4gVGhpcyBtYXkgaGF2ZSB0byBkdWUgd2l0aCBtYWluIGNhdXNlIG9mIGZpcmVzIGluIEZsb3JpZGEgY2hhbmdpbmcgZnJvbSByYWlscm9hZCB0byBsaWdodG5pbmcgcmVsYXRlZCBhYm91dCB0aGUgc2FtZSB0aW1lLCBhcyB3ZSBub3RlZCBlYXJsaWVyIG9uIHdoZW4gbG9va2luZyBhdCBjYXVzYXRpb24uICBBcyBKdWx5IGlzIHRoZSBtYWluIG1vbnRoIGZvciB0cm9waWNhbCBzdG9ybXMgYW5kIGxpZ2h0bmluZyBpbiBGbG9yaWRhIHRoaXMgaXMgYSBwb3NzaWJsZSBjYXVzZSBmb3IgdGhlIGhpZ2hlc3QgbW9udGggYmVjb21pbmcgbGF0ZXIgaW4gdGhlIHllYXIgdGhhbiBiZWZvcmUuICgyKSoqCgoKKDIpIGh0dHBzOi8vd3d3LndlYXRoZXIuZ292L21sYi9mbF9saWdodG5pbmdfY2xpbW8KCgo=